Use backend interface for labels and goto statements.
authorIan Lance Taylor <iant@google.com>
Tue, 5 Apr 2011 05:57:39 +0000 (05:57 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 5 Apr 2011 05:57:39 +0000 (05:57 +0000)
* 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.

From-SVN: r171968

gcc/go/ChangeLog
gcc/go/Make-lang.in
gcc/go/go-gcc.cc
gcc/go/gofrontend/backend.h
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo-tree.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/statements.cc

index b8a11f6d5d1dca718a477b45ca5e9148267091e3..657091a24496323debe6be8a2ed4c1ec2884cffa 100644 (file)
@@ -1,3 +1,17 @@
+2011-04-04  Ian Lance Taylor  <iant@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.
+
 2011-04-04  Ian Lance Taylor  <iant@google.com>
 
        * go-gcc.cc: #include "tree-iterator.h", "gimple.h", and "gogo.h".
index 67900d7749733901e048b24cc4009007db41ac4f..0dc8942061ae69106c92b26f610d48b1559f9ee0 100644 (file)
@@ -252,7 +252,7 @@ go/expressions.o: go/gofrontend/expressions.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
        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.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
 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 2785bf296dc743b3fa671adbf69fbe8389ba3880..ee100c6e9156492fb6430814f2f03f1f8fa52843 100644 (file)
@@ -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* 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;
@@ -276,6 +360,12 @@ tree_to_function(tree t)
   return new Bfunction(t);
 }
 
+tree
+expression_to_tree(Bexpression* be)
+{
+  return be->get_tree();
+}
+
 tree
 statement_to_tree(Bstatement* bs)
 {
index 959fc7862c061bf178567e26b49c51010f852afb..814263edc22c95f5a2f97215ad39921f64ac3323 100644 (file)
@@ -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)
index a0cfcfcdf7452f55d77e240f7b6fc2ef59508fd4..afd2191e857f6fb9155e7ca89b16b8da3c2b59a8 100644 (file)
@@ -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 Expression
   { 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 bd5945bd7ba6072c98f55643cca282263677c41c..53e43c7b519deb7f04996fa714aeb343a92e03d3 100644 (file)
@@ -1915,62 +1915,6 @@ Block::get_tree(Translate_context* context)
   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 5b3ac8cd9c28f9455c4fcf5d6119a2fb440d1031..31549ac233a94cff7f396f3e0303728c99b5928c 100644 (file)
@@ -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, bool is_global)
   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 87e2da6890b5a5c556e5cf69001c7e25dc878db1..cf126cdc282b43027f4bb677f362aaf3f9de01e5 100644 (file)
@@ -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 the backend representation for this label.
+  Blabel*
+  get_backend_label(Translate_context*);
 
-  // Return an expression for the address of this label.
-  tree
-  get_addr(source_location location);
+  // 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 3783fb83a519b3b52c89b120d78110e836c2aef3..854b329d9ecc456147587fb48ea12067cebda398 100644 (file)
@@ -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 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:
   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 Statement
   { 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_tree(Translate_context* context,
     }
 
   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(Translate_context* context)
   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_context* context,
       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_context* context,
        }
     }
 
-  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(Translate_context* context, int case_index,
                                  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.