This patch to the Go compiler uses the backend interface for labels and
goto statements.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


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

        * go-gcc.c (class Blabel): Define.
        (Gcc_backend::make_expression): New function.
        (get_identifier_from_string): New function.
        (Gcc_backend::label): New function.
        (Gcc_backend::label_definition_statement): New function.
        (Gcc_backend::goto_statement): New function.
        (Gcc_backend::label_address): New function.
        (expression_to_tree): New function.
        * Make-lang.in (go/expressions.o): Depend on
        go/gofrontend/backend.h.
        (go/gogo.o): Likewise.


Index: gcc/go/Make-lang.in
===================================================================
--- gcc/go/Make-lang.in	(revision 171959)
+++ gcc/go/Make-lang.in	(working copy)
@@ -252,7 +252,7 @@ go/expressions.o: go/gofrontend/expressi
 	intl.h $(TREE_H) $(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) \
 	realmpfr.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \
 	go/gofrontend/export.h $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \
-	$(GO_EXPRESSIONS_H)
+	go/gofrontend/backend.h $(GO_EXPRESSIONS_H)
 go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_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) \
@@ -264,7 +264,7 @@ go/gogo-tree.o: go/gofrontend/gogo-tree.
 go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \
 	go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \
 	$(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_IMPORT_H) \
-	go/gofrontend/export.h $(GO_GOGO_H)
+	go/gofrontend/export.h go/gofrontend/backend.h $(GO_GOGO_H)
 go/import.o: go/gofrontend/import.cc $(GO_SYSTEM_H) \
 	$(srcdir)/../include/filenames.h $(srcdir)/../include/simple-object.h \
 	$(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) go/gofrontend/export.h \
Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 171959)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -90,6 +90,14 @@ class Bfunction : public Gcc_tree
   { }
 };
 
+class Blabel : public Gcc_tree
+{
+ public:
+  Blabel(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
@@ -158,22 +166,46 @@ class Gcc_backend : public Backend
 
   // Statements.
 
-  // Create an assignment statement.
   Bstatement*
   assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location);
 
-  // Create a return statement.
   Bstatement*
   return_statement(Bfunction*, const std::vector<Bexpression*>&,
 		   source_location);
 
+  // Labels.
+
+  Blabel*
+  label(Bfunction*, const std::string& name, source_location);
+
+  Bstatement*
+  label_definition_statement(Blabel*);
+
+  Bstatement*
+  goto_statement(Blabel*, source_location);
+
+  Bexpression*
+  label_address(Blabel*, source_location);
+
  private:
+  // Make a Bexpression from a tree.
+  Bexpression*
+  make_expression(tree t)
+  { return new Bexpression(t); }
+
   // Make a Bstatement from a tree.
   Bstatement*
   make_statement(tree t)
   { return new Bstatement(t); }
 };
 
+// A helper function.
+
+static inline tree
+get_identifier_from_string(const std::string& str)
+{
+  return get_identifier_with_length(str.data(), str.length());
+}
 // Assignment.
 
 Bstatement*
@@ -249,6 +281,58 @@ Gcc_backend::return_statement(Bfunction*
   return this->make_statement(ret);
 }
 
+// Make a label.
+
+Blabel*
+Gcc_backend::label(Bfunction* function, const std::string& name,
+		   source_location location)
+{
+  tree decl;
+  if (name.empty())
+    decl = create_artificial_label(location);
+  else
+    {
+      tree id = get_identifier_from_string(name);
+      decl = build_decl(location, LABEL_DECL, id, void_type_node);
+      DECL_CONTEXT(decl) = function->get_tree();
+    }
+  return new Blabel(decl);
+}
+
+// Make a statement which defines a label.
+
+Bstatement*
+Gcc_backend::label_definition_statement(Blabel* label)
+{
+  tree lab = label->get_tree();
+  tree ret = fold_build1_loc(DECL_SOURCE_LOCATION(lab), LABEL_EXPR,
+			     void_type_node, lab);
+  return this->make_statement(ret);
+}
+
+// Make a goto statement.
+
+Bstatement*
+Gcc_backend::goto_statement(Blabel* label, source_location location)
+{
+  tree lab = label->get_tree();
+  tree ret = fold_build1_loc(location, GOTO_EXPR, void_type_node, lab);
+  return this->make_statement(ret);
+}
+
+// Get the address of a label.
+
+Bexpression*
+Gcc_backend::label_address(Blabel* label, source_location location)
+{
+  tree lab = label->get_tree();
+  TREE_USED(lab) = 1;
+  TREE_ADDRESSABLE(lab) = 1;
+  tree ret = fold_convert_loc(location, ptr_type_node,
+			      build_fold_addr_expr_loc(location, lab));
+  return this->make_expression(ret);
+}
+
 // The single backend.
 
 static Gcc_backend gcc_backend;
@@ -277,6 +361,12 @@ tree_to_function(tree t)
 }
 
 tree
+expression_to_tree(Bexpression* be)
+{
+  return be->get_tree();
+}
+
+tree
 statement_to_tree(Bstatement* bs)
 {
   return bs->get_tree();
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 171959)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -15,6 +15,7 @@
 #include "dataflow.h"
 #include "import.h"
 #include "export.h"
+#include "backend.h"
 #include "gogo.h"
 
 // Class Gogo.
@@ -4430,6 +4431,69 @@ Bindings::traverse(Traverse* traverse, b
   return TRAVERSE_CONTINUE;
 }
 
+// Class Label.
+
+// Get the backend representation for a label.
+
+Blabel*
+Label::get_backend_label(Translate_context* context)
+{
+  if (this->blabel_ == NULL)
+    {
+      Function* function = context->function()->func_value();
+      tree fndecl = function->get_decl();
+      Bfunction* bfunction = tree_to_function(fndecl);
+      this->blabel_ = context->backend()->label(bfunction, this->name_,
+						this->location_);
+    }
+  return this->blabel_;
+}
+
+// Return an expression for the address of this label.
+
+Bexpression*
+Label::get_addr(Translate_context* context, source_location location)
+{
+  Blabel* label = this->get_backend_label(context);
+  return context->backend()->label_address(label, location);
+}
+
+// Class Unnamed_label.
+
+// Get the backend representation for an unnamed label.
+
+Blabel*
+Unnamed_label::get_blabel(Translate_context* context)
+{
+  if (this->blabel_ == NULL)
+    {
+      Function* function = context->function()->func_value();
+      tree fndecl = function->get_decl();
+      Bfunction* bfunction = tree_to_function(fndecl);
+      this->blabel_ = context->backend()->label(bfunction, "",
+						this->location_);
+    }
+  return this->blabel_;
+}
+
+// Return a statement which defines this unnamed label.
+
+Bstatement*
+Unnamed_label::get_definition(Translate_context* context)
+{
+  Blabel* blabel = this->get_blabel(context);
+  return context->backend()->label_definition_statement(blabel);
+}
+
+// Return a goto statement to this unnamed label.
+
+Bstatement*
+Unnamed_label::get_goto(Translate_context* context, source_location location)
+{
+  Blabel* blabel = this->get_blabel(context);
+  return context->backend()->goto_statement(blabel, location);
+}
+
 // Class Package.
 
 Package::Package(const std::string& name, const std::string& unique_prefix,
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 171959)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -40,6 +40,9 @@ class Translate_context;
 class Backend;
 class Export;
 class Import;
+class Bexpression;
+class Bstatement;
+class Blabel;
 
 // This file declares the basic classes used to hold the internal
 // representation of Go which is built by the parser.
@@ -2115,7 +2118,7 @@ class Label
 {
  public:
   Label(const std::string& name)
-    : name_(name), location_(0), is_used_(false), decl_(NULL)
+    : name_(name), location_(0), is_used_(false), blabel_(NULL)
   { }
 
   // Return the label's name.
@@ -2151,13 +2154,15 @@ class Label
     this->location_ = location;
   }
 
-  // Return the LABEL_DECL for this decl.
-  tree
-  get_decl();
-
-  // Return an expression for the address of this label.
-  tree
-  get_addr(source_location location);
+  // Return the backend representation for this label.
+  Blabel*
+  get_backend_label(Translate_context*);
+
+  // Return an expression for the address of this label.  This is used
+  // to get the return address of a deferred function to see whether
+  // the function may call recover.
+  Bexpression*
+  get_addr(Translate_context*, source_location location);
 
  private:
   // The name of the label.
@@ -2167,8 +2172,8 @@ class Label
   source_location location_;
   // Whether the label has been used.
   bool is_used_;
-  // The LABEL_DECL.
-  tree decl_;
+  // The backend representation.
+  Blabel* blabel_;
 };
 
 // An unnamed label.  These are used when lowering loops.
@@ -2177,7 +2182,7 @@ class Unnamed_label
 {
  public:
   Unnamed_label(source_location location)
-    : location_(location), decl_(NULL)
+    : location_(location), blabel_(NULL)
   { }
 
   // Get the location where the label is defined.
@@ -2191,22 +2196,22 @@ class Unnamed_label
   { this->location_ = location; }
 
   // Return a statement which defines this label.
-  tree
-  get_definition();
+  Bstatement*
+  get_definition(Translate_context*);
 
   // Return a goto to this label from LOCATION.
-  tree
-  get_goto(source_location location);
+  Bstatement*
+  get_goto(Translate_context*, source_location location);
 
  private:
-  // Return the LABEL_DECL to use with GOTO_EXPR.
-  tree
-  get_decl();
+  // Return the backend representation.
+  Blabel*
+  get_blabel(Translate_context*);
 
   // The location where the label is defined.
   source_location location_;
-  // The LABEL_DECL.
-  tree decl_;
+  // The backend representation of this label.
+  Blabel* blabel_;
 };
 
 // An imported package.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 171959)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -33,6 +33,7 @@ extern "C"
 #include "import.h"
 #include "statements.h"
 #include "lex.h"
+#include "backend.h"
 #include "expressions.h"
 
 // Class Expression.
@@ -12595,8 +12596,11 @@ class Label_addr_expression : public Exp
   { return new Label_addr_expression(this->label_, this->location()); }
 
   tree
-  do_get_tree(Translate_context*)
-  { return this->label_->get_addr(this->location()); }
+  do_get_tree(Translate_context* context)
+  {
+    return expression_to_tree(this->label_->get_addr(context,
+						     this->location()));
+  }
 
  private:
   // The label whose address we are taking.
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 171959)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -2619,8 +2619,11 @@ class Bc_statement : public Statement
   { return false; }
 
   tree
-  do_get_tree(Translate_context*)
-  { return this->label_->get_goto(this->location()); }
+  do_get_tree(Translate_context* context)
+  {
+    return statement_to_tree(this->label_->get_goto(context,
+						    this->location()));
+  }
 
  private:
   // The label that this branches to.
@@ -2692,9 +2695,12 @@ Goto_statement::do_check_types(Gogo*)
 // Return the tree for the goto statement.
 
 tree
-Goto_statement::do_get_tree(Translate_context*)
+Goto_statement::do_get_tree(Translate_context* context)
 {
-  return this->build_stmt_1(GOTO_EXPR, this->label_->get_decl());
+  Blabel* blabel = this->label_->get_backend_label(context);
+  Bstatement* statement = context->backend()->goto_statement(blabel,
+							     this->location());
+  return statement_to_tree(statement);
 }
 
 // Make a goto statement.
@@ -2725,8 +2731,11 @@ class Goto_unnamed_statement : public St
   { return false; }
 
   tree
-  do_get_tree(Translate_context*)
-  { return this->label_->get_goto(this->location()); }
+  do_get_tree(Translate_context* context)
+  {
+    return statement_to_tree(this->label_->get_goto(context,
+						    this->location()));
+  }
 
  private:
   Unnamed_label* label_;
@@ -2754,9 +2763,12 @@ Label_statement::do_traverse(Traverse*)
 // Return a tree defining this label.
 
 tree
-Label_statement::do_get_tree(Translate_context*)
+Label_statement::do_get_tree(Translate_context* context)
 {
-  return this->build_stmt_1(LABEL_EXPR, this->label_->get_decl());
+  Blabel* blabel = this->label_->get_backend_label(context);
+  Bstatement* statement;
+  statement = context->backend()->label_definition_statement(blabel);
+  return statement_to_tree(statement);
 }
 
 // Make a label statement.
@@ -2783,8 +2795,8 @@ class Unnamed_label_statement : public S
   { return TRAVERSE_CONTINUE; }
 
   tree
-  do_get_tree(Translate_context*)
-  { return this->label_->get_definition(); }
+  do_get_tree(Translate_context* context)
+  { return statement_to_tree(this->label_->get_definition(context)); }
 
  private:
   // The label.
@@ -3134,7 +3146,10 @@ Case_clauses::Case_clause::get_constant_
     }
 
   if (!this->is_fallthrough_)
-    append_to_statement_list(break_label->get_goto(this->location_), stmt_list);
+    {
+      Bstatement* g = break_label->get_goto(context, this->location_);
+      append_to_statement_list(statement_to_tree(g), stmt_list);
+    }
 }
 
 // Class Case_clauses.
@@ -3387,7 +3402,8 @@ Constant_switch_statement::do_get_tree(T
   SET_EXPR_LOCATION(s, this->location());
   append_to_statement_list(s, &stmt_list);
 
-  append_to_statement_list(break_label->get_definition(), &stmt_list);
+  Bstatement* ldef = break_label->get_definition(context);
+  append_to_statement_list(statement_to_tree(ldef), &stmt_list);
 
   return stmt_list;
 }
@@ -4245,7 +4261,8 @@ Select_clauses::get_tree(Translate_conte
       tree stmt_list = NULL_TREE;
       append_to_statement_list(default_clause->get_statements_tree(context),
 			       &stmt_list);
-      append_to_statement_list(break_label->get_definition(), &stmt_list);
+      Bstatement* ldef = break_label->get_definition(context);
+      append_to_statement_list(statement_to_tree(ldef), &stmt_list);
       return stmt_list;
     }
 
@@ -4336,7 +4353,8 @@ Select_clauses::get_tree(Translate_conte
 	}
     }
 
-  append_to_statement_list(break_label->get_definition(), &stmt_list);
+  Bstatement* ldef = break_label->get_definition(context);
+  append_to_statement_list(statement_to_tree(ldef), &stmt_list);
 
   tree switch_stmt = build3(SWITCH_EXPR, sizetype, call, stmt_list, NULL_TREE);
   SET_EXPR_LOCATION(switch_stmt, location);
@@ -4358,10 +4376,11 @@ Select_clauses::add_clause_tree(Translat
 				  NULL_TREE, label),
 			   stmt_list);
   append_to_statement_list(clause->get_statements_tree(context), stmt_list);
-  tree g = bottom_label->get_goto(clause->statements() == NULL
-				  ? clause->location()
-				  : clause->statements()->end_location());
-  append_to_statement_list(g, stmt_list);
+  source_location gloc = (clause->statements() == NULL
+			  ? clause->location()
+			  : clause->statements()->end_location());
+  Bstatement* g = bottom_label->get_goto(context, gloc);
+  append_to_statement_list(statement_to_tree(g), stmt_list);
 }
 
 // Class Select_statement.
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(revision 171959)
+++ gcc/go/gofrontend/gogo-tree.cc	(working copy)
@@ -1915,62 +1915,6 @@ Block::get_tree(Translate_context* conte
   return bind;
 }
 
-// Get the LABEL_DECL for a label.
-
-tree
-Label::get_decl()
-{
-  if (this->decl_ == NULL)
-    {
-      tree id = get_identifier_from_string(this->name_);
-      this->decl_ = build_decl(this->location_, LABEL_DECL, id, void_type_node);
-      DECL_CONTEXT(this->decl_) = current_function_decl;
-    }
-  return this->decl_;
-}
-
-// Return an expression for the address of this label.
-
-tree
-Label::get_addr(source_location location)
-{
-  tree decl = this->get_decl();
-  TREE_USED(decl) = 1;
-  TREE_ADDRESSABLE(decl) = 1;
-  return fold_convert_loc(location, ptr_type_node,
-			  build_fold_addr_expr_loc(location, decl));
-}
-
-// Get the LABEL_DECL for an unnamed label.
-
-tree
-Unnamed_label::get_decl()
-{
-  if (this->decl_ == NULL)
-    this->decl_ = create_artificial_label(this->location_);
-  return this->decl_;
-}
-
-// Get the LABEL_EXPR for an unnamed label.
-
-tree
-Unnamed_label::get_definition()
-{
-  tree t = build1(LABEL_EXPR, void_type_node, this->get_decl());
-  SET_EXPR_LOCATION(t, this->location_);
-  return t;
-}
-
-// Return a goto to this label.
-
-tree
-Unnamed_label::get_goto(source_location location)
-{
-  tree t = build1(GOTO_EXPR, void_type_node, this->get_decl());
-  SET_EXPR_LOCATION(t, location);
-  return t;
-}
-
 // Return the integer type to use for a size.
 
 GO_EXTERN_C
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 171959)
+++ gcc/go/gofrontend/backend.h	(working copy)
@@ -27,6 +27,9 @@ class Bstatement;
 // The backend representation of a function definition.
 class Bfunction;
 
+// The backend representation of a label.
+class Blabel;
+
 // A list of backend types.
 typedef std::vector<Btype*> Btypes;
 
@@ -114,6 +117,30 @@ class Backend
   virtual Bstatement*
   return_statement(Bfunction*, const std::vector<Bexpression*>&,
 		   source_location) = 0;
+
+  // Labels.
+  
+  // Create a new label.  NAME will be empty if this is a label
+  // created by the frontend for a loop construct.  The location is
+  // where the the label is defined.
+  virtual Blabel*
+  label(Bfunction*, const std::string& name, source_location) = 0;
+
+  // Create a statement which defines a label.  This statement will be
+  // put into the codestream at the point where the label should be
+  // defined.
+  virtual Bstatement*
+  label_definition_statement(Blabel*) = 0;
+
+  // Create a goto statement to a label.
+  virtual Bstatement*
+  goto_statement(Blabel*, source_location) = 0;
+
+  // Create an expression for the address of a label.  This is used to
+  // get the return address of a deferred function which may call
+  // recover.
+  virtual Bexpression*
+  label_address(Blabel*, source_location) = 0;
 };
 
 // The backend interface has to define this function.
@@ -125,6 +152,7 @@ extern Backend* go_get_backend();
 
 extern Bexpression* tree_to_expr(tree);
 extern Bfunction* tree_to_function(tree);
+extern tree expression_to_tree(Bexpression*);
 extern tree statement_to_tree(Bstatement*);
 
 #endif // !defined(GO_BACKEND_H)

Reply via email to