public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Go patch committed: Use backend interface for blocks
@ 2011-04-19 18:37 Ian Lance Taylor
  0 siblings, 0 replies; only message in thread
From: Ian Lance Taylor @ 2011-04-19 18:37 UTC (permalink / raw)
  To: gcc-patches, gofrontend-dev

[-- Attachment #1: Type: text/plain, Size: 510 bytes --]

This patch to the Go frontend uses the backend interface for blocks.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian


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

	* go-gcc.cc (class Bblock): Define.
	(Gcc_backend::if_statement): Change then_block and else_block to
	Bblock*.
	(Gcc_backend::block): New function.
	(Gcc_backend::block_add_statements): New function.
	(Gcc_backend::block_statement): New function.
	(tree_to_block, block_to_tree): New functions.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 21034 bytes --]

Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 172693)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -92,6 +92,14 @@ class Bfunction : public Gcc_tree
   { }
 };
 
+class Bblock : public Gcc_tree
+{
+ public:
+  Bblock(tree t)
+    : Gcc_tree(t)
+  { }
+};
+
 class Bvariable : public Gcc_tree
 {
  public:
@@ -194,8 +202,8 @@ class Gcc_backend : public Backend
 		   source_location);
 
   Bstatement*
-  if_statement(Bexpression* condition, Bstatement* then_block,
-	       Bstatement* else_block, source_location);
+  if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
+	       source_location);
 
   Bstatement*
   switch_statement(Bexpression* value,
@@ -209,6 +217,18 @@ class Gcc_backend : public Backend
   Bstatement*
   statement_list(const std::vector<Bstatement*>&);
 
+  // Blocks.
+
+  Bblock*
+  block(Bfunction*, Bblock*, const std::vector<Bvariable*>&,
+	source_location, source_location);
+
+  void
+  block_add_statements(Bblock*, const std::vector<Bstatement*>&);
+
+  Bstatement*
+  block_statement(Bblock*);
+
   // Variables.
 
   Bvariable*
@@ -370,8 +390,8 @@ Gcc_backend::return_statement(Bfunction*
 // If.
 
 Bstatement*
-Gcc_backend::if_statement(Bexpression* condition, Bstatement* then_block,
-			  Bstatement* else_block, source_location location)
+Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
+			  Bblock* else_block, source_location location)
 {
   tree cond_tree = condition->get_tree();
   tree then_tree = then_block->get_tree();
@@ -481,6 +501,114 @@ Gcc_backend::statement_list(const std::v
   return this->make_statement(stmt_list);
 }
 
+// Make a block.  For some reason gcc uses a dual structure for
+// blocks: BLOCK tree nodes and BIND_EXPR tree nodes.  Since the
+// BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in
+// the Bblock.
+
+Bblock*
+Gcc_backend::block(Bfunction* function, Bblock* enclosing,
+		   const std::vector<Bvariable*>& vars,
+		   source_location start_location,
+		   source_location)
+{
+  tree block_tree = make_node(BLOCK);
+  if (enclosing == NULL)
+    {
+      // FIXME: Permitting FUNCTION to be NULL is a temporary measure
+      // until we have a proper representation of the init function.
+      tree fndecl;
+      if (function == NULL)
+	fndecl = current_function_decl;
+      else
+	fndecl = function->get_tree();
+      gcc_assert(fndecl != NULL_TREE);
+
+      // We may have already created a block for local variables when
+      // we take the address of a parameter.
+      if (DECL_INITIAL(fndecl) == NULL_TREE)
+	{
+	  BLOCK_SUPERCONTEXT(block_tree) = fndecl;
+	  DECL_INITIAL(fndecl) = block_tree;
+	}
+      else
+	{
+	  tree superblock_tree = DECL_INITIAL(fndecl);
+	  BLOCK_SUPERCONTEXT(block_tree) = superblock_tree;
+	  tree* pp;
+	  for (pp = &BLOCK_SUBBLOCKS(superblock_tree);
+	       *pp != NULL_TREE;
+	       pp = &BLOCK_CHAIN(*pp))
+	    ;
+	  *pp = block_tree;
+	}
+    }
+  else
+    {
+      tree superbind_tree = enclosing->get_tree();
+      tree superblock_tree = BIND_EXPR_BLOCK(superbind_tree);
+      gcc_assert(TREE_CODE(superblock_tree) == BLOCK);
+
+      BLOCK_SUPERCONTEXT(block_tree) = superblock_tree;
+      tree* pp;
+      for (pp = &BLOCK_SUBBLOCKS(superblock_tree);
+	   *pp != NULL_TREE;
+	   pp = &BLOCK_CHAIN(*pp))
+	;
+      *pp = block_tree;
+    }
+
+  tree* pp = &BLOCK_VARS(block_tree);
+  for (std::vector<Bvariable*>::const_iterator pv = vars.begin();
+       pv != vars.end();
+       ++pv)
+    {
+      *pp = (*pv)->get_tree();
+      if (*pp != error_mark_node)
+	pp = &DECL_CHAIN(*pp);
+    }
+  *pp = NULL_TREE;
+
+  TREE_USED(block_tree) = 1;
+
+  tree bind_tree = build3_loc(start_location, BIND_EXPR, void_type_node,
+			      BLOCK_VARS(block_tree), NULL_TREE, block_tree);
+  TREE_SIDE_EFFECTS(bind_tree) = 1;
+
+  return new Bblock(bind_tree);
+}
+
+// Add statements to a block.
+
+void
+Gcc_backend::block_add_statements(Bblock* bblock,
+				  const std::vector<Bstatement*>& statements)
+{
+  tree stmt_list = NULL_TREE;
+  for (std::vector<Bstatement*>::const_iterator p = statements.begin();
+       p != statements.end();
+       ++p)
+    {
+      tree s = (*p)->get_tree();
+      if (s != error_mark_node)
+	append_to_statement_list(s, &stmt_list);
+    }
+
+  tree bind_tree = bblock->get_tree();
+  gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR);
+  BIND_EXPR_BODY(bind_tree) = stmt_list;
+}
+
+// Return a block as a statement.
+
+Bstatement*
+Gcc_backend::block_statement(Bblock* bblock)
+{
+  tree bind_tree = bblock->get_tree();
+  gcc_assert(TREE_CODE(bind_tree) == BIND_EXPR);
+  return this->make_statement(bind_tree);
+}
+
 // Make a global variable.
 
 Bvariable*
@@ -665,6 +793,13 @@ tree_to_function(tree t)
   return new Bfunction(t);
 }
 
+Bblock*
+tree_to_block(tree t)
+{
+  gcc_assert(TREE_CODE(t) == BIND_EXPR);
+  return new Bblock(t);
+}
+
 tree
 expr_to_tree(Bexpression* be)
 {
@@ -678,6 +813,12 @@ stat_to_tree(Bstatement* bs)
 }
 
 tree
+block_to_tree(Bblock* bb)
+{
+  return bb->get_tree();
+}
+
+tree
 var_to_tree(Bvariable* bv)
 {
   return bv->get_tree();
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 172693)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -3285,6 +3285,48 @@ Block::may_fall_through() const
   return this->statements_.back()->may_fall_through();
 }
 
+// Convert a block to the backend representation.
+
+Bblock*
+Block::get_backend(Translate_context* context)
+{
+  Gogo* gogo = context->gogo();
+  Named_object* function = context->function();
+  std::vector<Bvariable*> vars;
+  vars.reserve(this->bindings_->size_definitions());
+  for (Bindings::const_definitions_iterator pv =
+	 this->bindings_->begin_definitions();
+       pv != this->bindings_->end_definitions();
+       ++pv)
+    {
+      if ((*pv)->is_variable() && !(*pv)->var_value()->is_parameter())
+	vars.push_back((*pv)->get_backend_variable(gogo, function));
+    }
+
+  // FIXME: Permitting FUNCTION to be NULL here is a temporary measure
+  // until we have a proper representation of the init function.
+  Bfunction* bfunction;
+  if (function == NULL)
+    bfunction = NULL;
+  else
+    bfunction = tree_to_function(function->func_value()->get_decl());
+  Bblock* ret = context->backend()->block(bfunction, context->bblock(),
+					  vars, this->start_location_,
+					  this->end_location_);
+
+  Translate_context subcontext(gogo, function, this, ret);
+  std::vector<Bstatement*> bstatements;
+  bstatements.reserve(this->statements_.size());
+  for (std::vector<Statement*>::const_iterator p = this->statements_.begin();
+       p != this->statements_.end();
+       ++p)
+    bstatements.push_back(tree_to_stat((*p)->get_tree(&subcontext)));
+
+  context->backend()->block_add_statements(ret, bstatements);
+
+  return ret;
+}
+
 // Class Variable.
 
 Variable::Variable(Type* type, Expression* init, bool is_global,
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 172693)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -43,6 +43,7 @@ class Export;
 class Import;
 class Bexpression;
 class Bstatement;
+class Bblock;
 class Bvariable;
 class Blabel;
 
@@ -767,9 +768,9 @@ class Block
   bool
   may_fall_through() const;
 
-  // Return a tree of the code in this block.
-  tree
-  get_tree(Translate_context*);
+  // Convert the block to the backend representation.
+  Bblock*
+  get_backend(Translate_context*);
 
   // Iterate over statements.
 
@@ -2507,9 +2508,9 @@ class Translate_context
 {
  public:
   Translate_context(Gogo* gogo, Named_object* function, Block* block,
-		    tree block_tree)
+		    Bblock* bblock)
     : gogo_(gogo), backend_(gogo->backend()), function_(function),
-      block_(block), block_tree_(block_tree), is_const_(false)
+      block_(block), bblock_(bblock), is_const_(false)
   { }
 
   // Accessors.
@@ -2530,9 +2531,9 @@ class Translate_context
   block()
   { return this->block_; }
 
-  tree
-  block_tree()
-  { return this->block_tree_; }
+  Bblock*
+  bblock()
+  { return this->bblock_; }
 
   bool
   is_const()
@@ -2548,12 +2549,15 @@ class Translate_context
   Gogo* gogo_;
   // The generator for the backend data structures.
   Backend* backend_;
-  // The function we are currently translating.
+  // The function we are currently translating.  NULL if not in a
+  // function, e.g., the initializer of a global variable.
   Named_object* function_;
-  // The block we are currently translating.
+  // The block we are currently translating.  NULL if not in a
+  // function.
   Block *block_;
-  // The BLOCK node for the current block.
-  tree block_tree_;
+  // The backend representation of the current block.  NULL if block_
+  // is NULL.
+  Bblock* bblock_;
   // Whether this is being evaluated in a constant context.  This is
   // used for type descriptor initializers.
   bool is_const_;
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 172693)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -428,12 +428,14 @@ Temporary_statement::do_get_tree(Transla
       gcc_assert(current_function_decl != NULL_TREE);
       DECL_CONTEXT(decl) = current_function_decl;
 
-      // We have to add this variable to the block so that it winds up
-      // in a BIND_EXPR.
-      tree block_tree = context->block_tree();
-      gcc_assert(block_tree != NULL_TREE);
+      // We have to add this variable to the BLOCK and the BIND_EXPR.
+      tree bind_tree = block_to_tree(context->bblock());
+      gcc_assert(bind_tree != NULL_TREE && TREE_CODE(bind_tree) == BIND_EXPR);
+      tree block_tree = BIND_EXPR_BLOCK(bind_tree);
+      gcc_assert(TREE_CODE(block_tree) == BLOCK);
       DECL_CHAIN(decl) = BLOCK_VARS(block_tree);
       BLOCK_VARS(block_tree) = decl;
+      BIND_EXPR_VARS(bind_tree) = BLOCK_VARS(block_tree);
 
       this->decl_ = decl;
     }
@@ -1518,13 +1520,22 @@ class Block_statement : public Statement
   { return this->block_->may_fall_through(); }
 
   tree
-  do_get_tree(Translate_context* context)
-  { return this->block_->get_tree(context); }
+  do_get_tree(Translate_context* context);
 
  private:
   Block* block_;
 };
 
+// Convert a block to the backend representation of a statement.
+
+tree
+Block_statement::do_get_tree(Translate_context* context)
+{
+  Bblock* bblock = this->block_->get_backend(context);
+  Bstatement* ret = context->backend()->block_statement(bblock);
+  return stat_to_tree(ret);
+}
+
 // Make a block statement.
 
 Statement*
@@ -2767,19 +2778,14 @@ If_statement::do_get_tree(Translate_cont
   gcc_assert(this->cond_->type()->is_boolean_type()
 	     || this->cond_->type()->is_error());
   tree cond_tree = this->cond_->get_tree(context);
-  tree then_tree = this->then_block_->get_tree(context);
-  tree else_tree = (this->else_block_ == NULL
-		    ? NULL_TREE
-		    : this->else_block_->get_tree(context));
-
+  Bblock* then_block = this->then_block_->get_backend(context);
+  Bblock* else_block = (this->else_block_ == NULL
+			? NULL
+			: this->else_block_->get_backend(context));
   Bexpression* cond_expr = tree_to_expr(cond_tree);
-  Bstatement* then_stat = tree_to_stat(then_tree);
-  Bstatement* else_stat = (else_tree == NULL_TREE
-			   ? NULL
-			   : tree_to_stat(else_tree));
   
-  Bstatement* ret = context->backend()->if_statement(cond_expr, then_stat,
-						     else_stat,
+  Bstatement* ret = context->backend()->if_statement(cond_expr, then_block,
+						     else_block,
 						     this->location());
   return stat_to_tree(ret);
 }
@@ -3056,7 +3062,10 @@ Case_clauses::Case_clause::get_backend(T
   if (this->statements_ == NULL)
     statements = NULL;
   else
-    statements = tree_to_stat(this->statements_->get_tree(context));
+    {
+      Bblock* bblock = this->statements_->get_backend(context);
+      statements = context->backend()->block_statement(bblock);
+    }
 
   Bstatement* break_stat;
   if (this->is_fallthrough_)
@@ -4070,7 +4079,8 @@ Select_clauses::Select_clause::get_state
 {
   if (this->statements_ == NULL)
     return NULL;
-  return tree_to_stat(this->statements_->get_tree(context));
+  Bblock* bblock = this->statements_->get_backend(context);
+  return context->backend()->block_statement(bblock);
 }
 
 // Class Select_clauses.
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(revision 172693)
+++ gcc/go/gofrontend/gogo-tree.cc	(working copy)
@@ -900,7 +900,7 @@ Named_object::get_tree(Gogo* gogo, Named
     case NAMED_OBJECT_CONST:
       {
 	Named_constant* named_constant = this->u_.const_value;
-	Translate_context subcontext(gogo, function, NULL, NULL_TREE);
+	Translate_context subcontext(gogo, function, NULL, NULL);
 	tree expr_tree = named_constant->expr()->get_tree(&subcontext);
 	if (expr_tree == error_mark_node)
 	  decl = error_mark_node;
@@ -1038,7 +1038,7 @@ Variable::get_init_tree(Gogo* gogo, Name
     }
   else
     {
-      Translate_context context(gogo, function, NULL, NULL_TREE);
+      Translate_context context(gogo, function, NULL, NULL);
       tree rhs_tree = this->init_->get_tree(&context);
       return Expression::convert_for_assignment(&context, this->type(),
 						this->init_->type(),
@@ -1059,8 +1059,9 @@ Variable::get_init_block(Gogo* gogo, Nam
   // TRY_CATCH_EXPR; if it does, we want to add to the end of the
   // regular statements.
 
-  Translate_context context(gogo, function, NULL, NULL_TREE);
-  tree block_tree = this->preinit_->get_tree(&context);
+  Translate_context context(gogo, function, NULL, NULL);
+  Bblock* bblock = this->preinit_->get_backend(&context);
+  tree block_tree = block_to_tree(bblock);
   if (block_tree == error_mark_node)
     return error_mark_node;
   gcc_assert(TREE_CODE(block_tree) == BIND_EXPR);
@@ -1472,21 +1473,22 @@ Function::build_tree(Gogo* gogo, Named_o
 	  BLOCK_VARS(block) = declare_vars;
 	  TREE_USED(block) = 1;
 
+	  bind = build3(BIND_EXPR, void_type_node, BLOCK_VARS(block),
+			NULL_TREE, block);
+	  TREE_SIDE_EFFECTS(bind) = 1;
+
 	  if (this->defer_stack_ != NULL)
 	    {
 	      Translate_context dcontext(gogo, named_function, this->block_,
-					 block);
+					 tree_to_block(bind));
 	      defer_init = this->defer_stack_->get_tree(&dcontext);
 	    }
-
-	  bind = build3(BIND_EXPR, void_type_node, BLOCK_VARS(block),
-			NULL_TREE, block);
-	  TREE_SIDE_EFFECTS(bind) = 1;
 	}
 
       // Build the trees for all the statements in the function.
-      Translate_context context(gogo, named_function, NULL, NULL_TREE);
-      tree code = this->block_->get_tree(&context);
+      Translate_context context(gogo, named_function, NULL, NULL);
+      Bblock* bblock = this->block_->get_backend(&context);
+      tree code = block_to_tree(bblock);
 
       tree init = NULL_TREE;
       tree except = NULL_TREE;
@@ -1681,95 +1683,6 @@ Function::return_value(Gogo* gogo, Named
     }
 }
 
-// Get a tree for the statements in a block.
-
-tree
-Block::get_tree(Translate_context* context)
-{
-  Gogo* gogo = context->gogo();
-
-  tree block = make_node(BLOCK);
-
-  // Put the new block into the block tree.
-
-  if (context->block() == NULL)
-    {
-      tree fndecl;
-      if (context->function() != NULL)
-	fndecl = context->function()->func_value()->get_decl();
-      else
-	fndecl = current_function_decl;
-      gcc_assert(fndecl != NULL_TREE);
-
-      // We may have already created a block for the receiver.
-      if (DECL_INITIAL(fndecl) == NULL_TREE)
-	{
-	  BLOCK_SUPERCONTEXT(block) = fndecl;
-	  DECL_INITIAL(fndecl) = block;
-	}
-      else
-	{
-	  tree superblock_tree = DECL_INITIAL(fndecl);
-	  BLOCK_SUPERCONTEXT(block) = superblock_tree;
-	  gcc_assert(BLOCK_CHAIN(block) == NULL_TREE);
-	  BLOCK_CHAIN(block) = block;
-	}
-    }
-  else
-    {
-      tree superblock_tree = context->block_tree();
-      BLOCK_SUPERCONTEXT(block) = superblock_tree;
-      tree* pp;
-      for (pp = &BLOCK_SUBBLOCKS(superblock_tree);
-	   *pp != NULL_TREE;
-	   pp = &BLOCK_CHAIN(*pp))
-	;
-      *pp = block;
-    }
-
-  // Expand local variables in the block.
-
-  tree* pp = &BLOCK_VARS(block);
-  for (Bindings::const_definitions_iterator pv =
-	 this->bindings_->begin_definitions();
-       pv != this->bindings_->end_definitions();
-       ++pv)
-    {
-      if ((*pv)->is_variable() && !(*pv)->var_value()->is_parameter())
-	{
-	  Bvariable* var = (*pv)->get_backend_variable(gogo,
-						       context->function());
-	  *pp = var_to_tree(var);
-	  if (*pp != error_mark_node)
-	    pp = &DECL_CHAIN(*pp);
-	}
-    }
-  *pp = NULL_TREE;
-
-  Translate_context subcontext(gogo, context->function(), this, block);
-
-  tree statements = NULL_TREE;
-
-  // Expand the statements.
-
-  for (std::vector<Statement*>::const_iterator p = this->statements_.begin();
-       p != this->statements_.end();
-       ++p)
-    {
-      tree statement = (*p)->get_tree(&subcontext);
-      if (statement != error_mark_node)
-	append_to_statement_list(statement, &statements);
-    }
-
-  TREE_USED(block) = 1;
-
-  tree bind = build3(BIND_EXPR, void_type_node, BLOCK_VARS(block), statements,
-		     block);
-  TREE_SIDE_EFFECTS(bind) = 1;
-
-  return bind;
-}
-
 // Return the integer type to use for a size.
 
 GO_EXTERN_C
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 172693)
+++ 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 block.
+class Bblock;
+
 // The backend representation of a variable.
 class Bvariable;
 
@@ -139,8 +142,8 @@ class Backend
 
   // Create an if statement.  ELSE_BLOCK may be NULL.
   virtual Bstatement*
-  if_statement(Bexpression* condition, Bstatement* then_block,
-	       Bstatement* else_block, source_location) = 0;
+  if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
+	       source_location) = 0;
 
   // Create a switch statement where the case values are constants.
   // CASES and STATEMENTS must have the same number of entries.  If
@@ -163,6 +166,35 @@ class Backend
   virtual Bstatement*
   statement_list(const std::vector<Bstatement*>&) = 0;
 
+  // Blocks.
+
+  // Create a block.  The frontend will call this function when it
+  // starts converting a block within a function.  FUNCTION is the
+  // current function.  ENCLOSING is the enclosing block; it will be
+  // NULL for the top-level block in a function.  VARS is the list of
+  // local variables defined within this block; each entry will be
+  // created by the local_variable function.  START_LOCATION is the
+  // location of the start of the block, more or less the location of
+  // the initial curly brace.  END_LOCATION is the location of the end
+  // of the block, more or less the location of the final curly brace.
+  // The statements will be added after the block is created.
+  virtual Bblock*
+  block(Bfunction* function, Bblock* enclosing,
+	const std::vector<Bvariable*>& vars,
+	source_location start_location, source_location end_location) = 0;
+
+  // Add the statements to a block.  The block is created first.  Then
+  // the statements are created.  Then the statements are added to the
+  // block.  This will called exactly once per block.  The vector may
+  // be empty if there are no statements.
+  virtual void
+  block_add_statements(Bblock*, const std::vector<Bstatement*>&) = 0;
+
+  // Return the block as a statement.  This is used to include a block
+  // in a list of statements.
+  virtual Bstatement*
+  block_statement(Bblock*) = 0;
+
   // Variables.
 
   // Create an error variable.  This is used for cases which should
@@ -250,8 +282,10 @@ extern Btype* tree_to_type(tree);
 extern Bexpression* tree_to_expr(tree);
 extern Bstatement* tree_to_stat(tree);
 extern Bfunction* tree_to_function(tree);
+extern Bblock* tree_to_block(tree);
 extern tree expr_to_tree(Bexpression*);
 extern tree stat_to_tree(Bstatement*);
+extern tree block_to_tree(Bblock*);
 extern tree var_to_tree(Bvariable*);
 
 #endif // !defined(GO_BACKEND_H)
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 172393)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -4470,7 +4470,7 @@ Array_type::get_length_tree(Gogo* gogo)
 
 	  // Make up a translation context for the array length
 	  // expression.  FIXME: This won't work in general.
-	  Translate_context context(gogo, NULL, NULL, NULL_TREE);
+	  Translate_context context(gogo, NULL, NULL, NULL);
 	  tree len = this->length_->get_tree(&context);
 	  if (len != error_mark_node)
 	    {

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-04-19 18:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-19 18:37 Go patch committed: Use backend interface for blocks Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).