diff mbox

Go patch committed: Remove old escape analysis code

Message ID CAOyqgcWCo-Ay1ficvF-PAEPEKZziKv8RDgT4OY-P2Wv996sO0A@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor April 29, 2016, 5:33 p.m. UTC
This patch by Chris Manghane removes the old escape analysis code that
never quite worked.  He has written a series of patches that implement
working escape analysis.  I will be working through reviewing those.
This patch bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.
Committed to mainline.

Ian

2016-04-29  Chris Manghane  <cmang@google.com>

* Make-lang.in (GO_OBJS): Remove go/dataflow.o, go/escape.o.
diff mbox

Patch

Index: gcc/go/Make-lang.in
===================================================================
--- gcc/go/Make-lang.in	(revision 234304)
+++ gcc/go/Make-lang.in	(working copy)
@@ -50,8 +50,6 @@  go-warn = $(STRICT_WARN)
 
 GO_OBJS = \
 	go/ast-dump.o \
-	go/dataflow.o \
-	go/escape.o \
 	go/export.o \
 	go/expressions.o \
 	go/go-backend.o \
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 235608)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-50b2b468a85045c66d60112dc094c31ec4897123
+46b108136c0d102f181f0cc7c398e3db8c4d08a3
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/dataflow.cc
===================================================================
--- gcc/go/gofrontend/dataflow.cc	(revision 234304)
+++ gcc/go/gofrontend/dataflow.cc	(working copy)
@@ -1,299 +0,0 @@ 
-// dataflow.cc -- Go frontend dataflow.
-
-// Copyright 2009 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.
-
-#include "go-system.h"
-
-#include "gogo.h"
-#include "expressions.h"
-#include "statements.h"
-#include "dataflow.h"
-
-// This class is used to traverse the tree to look for uses of
-// variables.
-
-class Dataflow_traverse_expressions : public Traverse
-{
- public:
-  Dataflow_traverse_expressions(Dataflow* dataflow, Statement* statement)
-    : Traverse(traverse_blocks | traverse_expressions),
-      dataflow_(dataflow), statement_(statement)
-  { }
-
- protected:
-  // Only look at top-level expressions: do not descend into blocks.
-  // They will be examined via Dataflow_traverse_statements.
-  int
-  block(Block*)
-  { return TRAVERSE_SKIP_COMPONENTS; }
-
-  int
-  expression(Expression**);
-
- private:
-  // The dataflow information.
-  Dataflow* dataflow_;
-  // The Statement in which we are looking.
-  Statement* statement_;
-};
-
-// Given an expression, return the Named_object that it refers to, if
-// it is a local variable.
-
-static Named_object*
-get_var(Expression* expr)
-{
-  Var_expression* ve = expr->var_expression();
-  if (ve == NULL)
-    return NULL;
-  Named_object* no = ve->named_object();
-  go_assert(no->is_variable() || no->is_result_variable());
-  if (no->is_variable() && no->var_value()->is_global())
-    return NULL;
-  return no;
-}
-
-// Look for a reference to a variable in an expression.
-
-int
-Dataflow_traverse_expressions::expression(Expression** expr)
-{
-  Named_object* no = get_var(*expr);
-  if (no != NULL)
-    this->dataflow_->add_ref(no, this->statement_);
-  return TRAVERSE_CONTINUE;
-}
-
-// This class is used to handle an assignment statement.
-
-class Dataflow_traverse_assignment : public Traverse_assignments
-{
- public:
-  Dataflow_traverse_assignment(Dataflow* dataflow, Statement* statement)
-    : dataflow_(dataflow), statement_(statement)
-  { }
-
- protected:
-  void
-  initialize_variable(Named_object*);
-
-  void
-  assignment(Expression** lhs, Expression** rhs);
-
-  void
-  value(Expression**, bool, bool);
-
- private:
-  // The dataflow information.
-  Dataflow* dataflow_;
-  // The Statement in which we are looking.
-  Statement* statement_;
-};
-
-// Handle a variable initialization.
-
-void
-Dataflow_traverse_assignment::initialize_variable(Named_object* var)
-{
-  Expression* init = var->var_value()->init();
-  this->dataflow_->add_def(var, init, this->statement_, true);
-  if (init != NULL)
-    {
-      Expression* e = init;
-      this->value(&e, true, true);
-      go_assert(e == init);
-    }
-}
-
-// Handle an assignment in a statement.
-
-void
-Dataflow_traverse_assignment::assignment(Expression** plhs, Expression** prhs)
-{
-  Named_object* no = get_var(*plhs);
-  if (no != NULL)
-    {
-      Expression* rhs = prhs == NULL ? NULL : *prhs;
-      this->dataflow_->add_def(no, rhs, this->statement_, false);
-    }
-  else
-    {
-      // If this is not a variable it may be some computed lvalue, and
-      // we want to look for references to variables in that lvalue.
-      this->value(plhs, false, false);
-    }
-  if (prhs != NULL)
-    this->value(prhs, true, false);
-}
-
-// Handle a value in a statement.
-
-void
-Dataflow_traverse_assignment::value(Expression** pexpr, bool, bool)
-{
-  Named_object* no = get_var(*pexpr);
-  if (no != NULL)
-    this->dataflow_->add_ref(no, this->statement_);
-  else
-    {
-      Dataflow_traverse_expressions dte(this->dataflow_, this->statement_);
-      Expression::traverse(pexpr, &dte);
-    }
-}
-
-// This class is used to traverse the tree to look for statements.
-
-class Dataflow_traverse_statements : public Traverse
-{
- public:
-  Dataflow_traverse_statements(Dataflow* dataflow)
-    : Traverse(traverse_statements),
-      dataflow_(dataflow)
-  { }
-
- protected:
-  int
-  statement(Block*, size_t* pindex, Statement*);
-
- private:
-  // The dataflow information.
-  Dataflow* dataflow_;
-};
-
-// For each Statement, we look for expressions.
-
-int
-Dataflow_traverse_statements::statement(Block* block, size_t* pindex,
-					Statement *statement)
-{
-  Dataflow_traverse_assignment dta(this->dataflow_, statement);
-
-  // For thunk statements, make sure to traverse the call expression to
-  // find any reference to a variable being used as an argument.
-  if (!statement->traverse_assignments(&dta)
-      || statement->thunk_statement() != NULL)
-    {
-      // Case statements in selects will be lowered into temporaries at this
-      // point so our dataflow analysis will miss references between a/c and ch
-      // in case statements of the form a,c := <-ch.  Do a special dataflow
-      // analysis for select statements here; the analysis for the blocks will
-      // be handled as usual.
-      if (statement->select_statement() != NULL)
-	statement->select_statement()->analyze_dataflow(this->dataflow_);
-
-      Dataflow_traverse_expressions dte(this->dataflow_, statement);
-      statement->traverse(block, pindex, &dte);
-    }
-  return TRAVERSE_CONTINUE;
-}
-
-// Compare variables.
-
-bool
-Dataflow::Compare_vars::operator()(const Named_object* no1,
-				   const Named_object* no2) const
-{
-  if (no1->name() < no2->name())
-    return true;
-  if (no1->name() > no2->name())
-    return false;
-
-  // We can have two different variables with the same name.
-  Location loc1 = no1->location();
-  Location loc2 = no2->location();
-  if (loc1 < loc2)
-    return false;
-  if (loc1 > loc2)
-    return true;
-  if (Linemap::is_predeclared_location(loc1))
-    return false;
-
-  if (no1 == no2
-      || (no1->is_result_variable()
-	  && no2->is_result_variable())
-      || ((no1->is_variable()
-	   && no1->var_value()->is_type_switch_var())
-	  && (no2->is_variable()
-	      && no2->var_value()->is_type_switch_var())))
-    return false;
-
-  // We can't have two variables with the same name in the same
-  // location unless they are type switch variables which share the same
-  // fake location.
-  go_unreachable();
-}
-
-// Class Dataflow.
-
-Dataflow::Dataflow()
-  : defs_(), refs_()
-{
-}
-
-// Build the dataflow information.
-
-void
-Dataflow::initialize(Gogo* gogo)
-{
-  Dataflow_traverse_statements dts(this);
-  gogo->traverse(&dts);
-}
-
-// Add a definition of a variable.
-
-void
-Dataflow::add_def(Named_object* var, Expression* val, Statement* statement,
-		  bool is_init)
-{
-  Defs* defnull = NULL;
-  std::pair<Defmap::iterator, bool> ins =
-    this->defs_.insert(std::make_pair(var, defnull));
-  if (ins.second)
-    ins.first->second = new Defs;
-  Def def;
-  def.statement = statement;
-  def.val = val;
-  def.is_init = is_init;
-  ins.first->second->push_back(def);
-}
-
-// Add a reference to a variable.
-
-void
-Dataflow::add_ref(Named_object* var, Statement* statement)
-{
-  Refs* refnull = NULL;
-  std::pair<Refmap::iterator, bool> ins =
-    this->refs_.insert(std::make_pair(var, refnull));
-  if (ins.second)
-    ins.first->second = new Refs;
-  Ref ref;
-  ref.statement = statement;
-  ins.first->second->push_back(ref);
-}
-
-// Return the definitions of a variable.
-
-const Dataflow::Defs*
-Dataflow::find_defs(Named_object* var) const
-{
-  Defmap::const_iterator p = this->defs_.find(var);
-  if (p == this->defs_.end())
-    return NULL;
-  else
-    return p->second;
-}
-
-// Return the references of a variable.
-
-const Dataflow::Refs*
-Dataflow::find_refs(Named_object* var) const
-{
-  Refmap::const_iterator p = this->refs_.find(var);
-  if (p == this->refs_.end())
-    return NULL;
-  else
-    return p->second;
-}
Index: gcc/go/gofrontend/dataflow.h
===================================================================
--- gcc/go/gofrontend/dataflow.h	(revision 234304)
+++ gcc/go/gofrontend/dataflow.h	(working copy)
@@ -1,91 +0,0 @@ 
-// dataflow.h -- Go frontend dataflow.    -*- C++ -*-
-
-// Copyright 2009 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_DATAFLOW_H
-#define GO_DATAFLOW_H
-
-class Expression;
-class Named_object;
-class Statement;
-
-// Dataflow information about the Go program.
-
-class Dataflow
-{
- public:
-  // A variable definition.
-  struct Def
-  {
-    // The statement where the variable is defined.
-    Statement* statement;
-    // The value to which the variable is set.  This may be NULL.
-    Expression* val;
-    // Whether this is an initialization of the variable.
-    bool is_init;
-  };
-
-  // A variable reference.
-  struct Ref
-  {
-    // The statement where the variable is referenced.
-    Statement* statement;
-  };
-
-  // A list of defs.
-  typedef std::vector<Def> Defs;
-
-  // A list of refs.
-  typedef std::vector<Ref> Refs;
-
-  Dataflow();
-
-  // Initialize the dataflow information.
-  void
-  initialize(Gogo*);
-
-  // Add a definition of a variable.  STATEMENT assigns a value to
-  // VAR.  VAL is the value if it is known, NULL otherwise.
-  void
-  add_def(Named_object* var, Expression* val, Statement* statement,
-	  bool is_init);
-
-  // Add a reference to a variable.  VAR is the variable, and
-  // STATEMENT is the statement which refers to it.
-  void
-  add_ref(Named_object* var, Statement* statement);
-
-  // Return the definitions of VAR--the places where it is set.
-  const Defs*
-  find_defs(Named_object* var) const;
-
-  // Return the references to VAR--the places where it is used.
-  const Refs*
-  find_refs(Named_object* var) const;
-
- private:
-  // Order variables in the map.
-  struct Compare_vars
-  {
-    bool
-    operator()(const Named_object*, const Named_object*) const;
-  };
-
-  // Map from variables to a list of defs of the variable.  We use a
-  // map rather than a hash table because the order in which we
-  // process variables may affect the resulting code.
-  typedef std::map<Named_object*, Defs*, Compare_vars> Defmap;
-
-  // Map from variables to a list of refs to the vairable.
-  typedef std::map<Named_object*, Refs*, Compare_vars> Refmap;
-
-  // Variable defs.
-  Defmap defs_;
-  // Variable refs;
-  Refmap refs_;
-};
-
-
-#endif // !defined(GO_DATAFLOW_H)
Index: gcc/go/gofrontend/escape.cc
===================================================================
--- gcc/go/gofrontend/escape.cc	(revision 234304)
+++ gcc/go/gofrontend/escape.cc	(working copy)
@@ -1,1669 +0,0 @@ 
-// escape.cc -- Go frontend escape analysis.
-
-// Copyright 2015 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.
-
-#include "go-system.h"
-
-#include <fstream>
-
-#include "go-c.h"
-#include "go-dump.h"
-#include "go-optimize.h"
-#include "types.h"
-#include "statements.h"
-#include "expressions.h"
-#include "dataflow.h"
-#include "gogo.h"
-#include "escape.h"
-
-// Class Node.
-
-Node::Node(Node_classification classification, Named_object* object)
-  : classification_(classification), object_(object)
-{
-  // Give every node a unique ID for representation purposes.
-  static int count;
-  this->id_ = count++;
-}
-
-Node::~Node()
-{
-}
-
-// Make a call node for FUNCTION.
-
-Node*
-Node::make_call(Named_object* function)
-{
-  return new Call_node(function);
-}
-
-// Make a connection node for OBJECT.
-
-Node*
-Node::make_connection(Named_object* object, Escapement_lattice e)
-{
-  return new Connection_node(object, e);
-}
-
-// Return this node's label, which will be the name seen in the graphical
-// representation.
-
-const std::string&
-Node::label()
-{
-  if (this->label_.empty())
-    {
-      this->label_ = "[label=\"";
-      this->label_ += this->object_->name();
-      this->label_ += "\"]";
-    }
-  return this->label_;
-}
-
-// Class Call_node.
-
-Call_node::Call_node(Named_object* function)
-  : Node(NODE_CALL, function)
-{ go_assert(function->is_function() || function->is_function_declaration()); }
-
-const std::string&
-Call_node::name()
-{
-  if (this->get_name().empty())
-    {
-      char buf[30];
-      snprintf(buf, sizeof buf, "CallNode%d", this->id());
-      this->set_name(std::string(buf));
-    }
-  return this->get_name();
-}
-
-// Class Connection_node.
-
-const std::string&
-Connection_node::name()
-{
-  if (this->get_name().empty())
-    {
-      char buf[30];
-      snprintf(buf, sizeof buf, "ConnectionNode%d", this->id());
-      this->set_name(std::string(buf));
-    }
-  return this->get_name();
-}
-
-const std::string&
-Connection_node::label()
-{
-  if (this->get_label().empty())
-    {
-      std::string label = "[label=\"";
-      label += this->object()->name();
-      label += "\",color=";
-      switch (this->escape_state_)
-      {
-      case ESCAPE_GLOBAL:
-	label += "red";
-	break;
-      case ESCAPE_ARG:
-	label += "blue";
-	break;
-      case ESCAPE_NONE:
-	label += "black";
-	break;
-      }
-      label += "]";
-      this->set_label(label);
-    }
-  return this->get_label();
-}
-
-// Dump a connection node and its edges to a dump file.
-
-void
-Connection_node::dump_connection(Connection_dump_context* cdc)
-{
-  cdc->write_string(this->name() + this->label());
-  cdc->write_c_string("\n");
-
-  for (std::set<Node*>::const_iterator p = this->edges().begin();
-       p != this->edges().end();
-       ++p)
-    {
-      cdc->write_string(this->name());
-      cdc->write_c_string("->");
-
-      if ((*p)->object()->is_function())
-	{
-	  char buf[100];
-	  snprintf(buf, sizeof buf, "dummy%d[lhead=cluster%d]",
-		   (*p)->id(), (*p)->id());
-	  cdc->write_c_string(buf);
-	}
-      else
-	cdc->write_string((*p)->name());
-      cdc->write_c_string("\n");
-    }
-}
-
-// The -fgo-dump-calls flag to activate call graph dumps in GraphViz DOT format.
-
-Go_dump call_graph_dump_flag("calls");
-
-// Class Call_dump_context.
-
-Call_dump_context::Call_dump_context(std::ostream* out)
-  : ostream_(out), gogo_(NULL)
-{ }
-
-// Dump files will be named %basename%.calls.dot
-
-const char* kCallDumpFileExtension = ".calls.dot";
-
-// Dump the call graph in DOT format.
-
-void
-Call_dump_context::dump(Gogo* gogo, const char* basename)
-{
-  std::ofstream* out = new std::ofstream();
-  std::string dumpname(basename);
-  dumpname += kCallDumpFileExtension;
-  out->open(dumpname.c_str());
-
-  if (out->fail())
-    {
-      error("cannot open %s:%m, -fgo-dump-calls ignored", dumpname.c_str());
-      return;
-    }
-
-  this->gogo_ = gogo;
-  this->ostream_ = out;
-
-  this->write_string("digraph CallGraph {\n");
-  std::set<Node*> call_graph = gogo->call_graph();
-
-  // Generate GraphViz nodes for each node.
-  for (std::set<Node*>::const_iterator p = call_graph.begin();
-       p != call_graph.end();
-       ++p)
-    {
-      this->write_string((*p)->name() + (*p)->label());
-      this->write_c_string("\n");
-      
-      // Generate a graphical representation of the caller-callee relationship.
-      std::set<Node*> callees = (*p)->edges();
-      for (std::set<Node*>::const_iterator ce = callees.begin();
-	   ce != callees.end();
-	   ++ce)
-	{
-	  this->write_string((*p)->name() + "->" + (*ce)->name());
-	  this->write_c_string("\n");
-	}
-    }
-  this->write_string("}");
-  out->close();
-}
-
-// Dump the Call Graph of the program to the dump file.
-
-void Gogo::dump_call_graph(const char* basename)
-{
-  if (::call_graph_dump_flag.is_enabled())
-    {
-      Call_dump_context cdc;
-      cdc.dump(this, basename);
-    }
-}
-
-// Implementation of String_dump interface.
-
-void
-Call_dump_context::write_c_string(const char* s)
-{
-  this->ostream() << s;
-}
-
-void
-Call_dump_context::write_string(const std::string& s)
-{
-  this->ostream() << s;
-}
-
-// The -fgo-dump-conns flag to activate connection graph dumps in
-// GraphViz DOT format.
-
-Go_dump connection_graph_dump_flag("conns");
-
-// Class Connection_dump_context.
-
-Connection_dump_context::Connection_dump_context(std::ostream* out)
-  : ostream_(out), gogo_(NULL)
-{ }
-
-// Dump files will be named %basename%.conns.dot
-
-const char* kConnectionDumpFileExtension = ".conns.dot";
-
-// Dump the connection graph in DOT format.
-
-void
-Connection_dump_context::dump(Gogo* gogo, const char* basename)
-{
-  std::ofstream* out = new std::ofstream();
-  std::string dumpname(basename);
-  dumpname += kConnectionDumpFileExtension;
-  out->open(dumpname.c_str());
-
-  if (out->fail())
-    {
-      error("cannot open %s:%m, -fgo-dump-conns ignored", dumpname.c_str());
-      return;
-    }
-
-  this->gogo_ = gogo;
-  this->ostream_ = out;
-
-  this->write_string("digraph ConnectionGraph {\n");
-  this->write_string("compound=true\n");
-
-  // Dump global objects.
-  std::set<Node*> globals = this->gogo_->global_connections();
-  this->write_c_string("subgraph globals{\n");
-  this->write_c_string("label=\"NonLocalGraph\"\n");
-  this->write_c_string("color=red\n");
-  for (std::set<Node*>::const_iterator p1 = globals.begin();
-       p1 != globals.end();
-       ++p1)
-    (*p1)->connection_node()->dump_connection(this);
-  this->write_c_string("}\n");
-
-  std::set<Node*> roots = this->gogo_->connection_roots();
-  for (std::set<Node*>::const_reverse_iterator p1 = roots.rbegin();
-       p1 != roots.rend();
-       ++p1)
-    {
-      std::set<Node*> objects = (*p1)->connection_node()->objects();
-
-      char buf[150];
-      snprintf(buf, sizeof buf, "subgraph cluster%d", (*p1)->id());
-      this->write_c_string(buf);
-      this->write_string("{\n");
-      snprintf(buf, sizeof buf, "dummy%d[shape=point,style=invis]\n",
-	       (*p1)->id());
-      this->write_c_string(buf);
-      this->write_string("label = \"" + (*p1)->object()->name() + "\"\n");
-
-      for (std::set<Node*>::const_iterator p2 = objects.begin();
-	   p2 != objects.end();
-	   ++p2)
-	(*p2)->connection_node()->dump_connection(this);
-
-      this->write_string("}\n");
-    }
-  this->write_string("}");
-  out->close();
-}
-
-void
-Gogo::dump_connection_graphs(const char* basename)
-{
-  if (::connection_graph_dump_flag.is_enabled())
-    {
-      Connection_dump_context cdc;
-      cdc.dump(this, basename);
-    }
-}
-
-// Implementation of String_dump interface.
-
-void
-Connection_dump_context::write_c_string(const char* s)
-{
-  this->ostream() << s;
-}
-
-void
-Connection_dump_context::write_string(const std::string& s)
-{
-  this->ostream() << s;
-}
-
-// A traversal class used to build a call graph for this program.
-
-class Build_call_graph : public Traverse
-{
- public:
-  Build_call_graph(Gogo* gogo)
-    : Traverse(traverse_functions
-	       | traverse_expressions),
-      gogo_(gogo), current_function_(NULL)
-  { }
-
-  int
-  function(Named_object*);
-
-  int
-  expression(Expression**);
-
- private:
-  // The IR.
-  Gogo* gogo_;
-  // The current function being traversed, for reference when traversing the
-  // function body.
-  Named_object* current_function_;
-};
-
-// Add each function to the call graph and then traverse each function's
-// body to find callee functions.
-
-int
-Build_call_graph::function(Named_object* fn)
-{
-  this->gogo_->add_call_node(fn);
-  go_assert(this->current_function_ == NULL);
-  this->current_function_ = fn;
-  fn->func_value()->traverse(this);
-  this->current_function_ = NULL;
-  return TRAVERSE_CONTINUE;
-}
-
-// Find function calls and add them as callees to CURRENT_FUNCTION.
-
-int
-Build_call_graph::expression(Expression** pexpr)
-{
-  if (this->current_function_ == NULL)
-    return TRAVERSE_CONTINUE;
-
-  Expression* expr = *pexpr;
-  Named_object* fn;
-  if (expr->call_expression() != NULL)
-    {
-      Func_expression* func = expr->call_expression()->fn()->func_expression();
-      if (func == NULL)
-	{
-	  // This is probably a variable holding a function value or a closure.
-	  return TRAVERSE_CONTINUE;
-	}
-      fn = func->named_object();
-    }
-  else if (expr->func_expression() != NULL)
-    fn = expr->func_expression()->named_object();
-  else
-    return TRAVERSE_CONTINUE;
-
-  Node* caller = this->gogo_->lookup_call_node(this->current_function_);
-  go_assert(caller != NULL);
-
-  // Create the callee here if it hasn't been seen yet.  This could also be a
-  // function defined in another package.
-  Node* callee = this->gogo_->add_call_node(fn);
-  caller->add_edge(callee);
-  return TRAVERSE_CONTINUE;
-}
-
-// Build the call graph.
-
-void
-Gogo::build_call_graph()
-{
-  Build_call_graph build_calls(this);
-  this->traverse(&build_calls);
-}
-
-// A traversal class used to build a connection graph for each node in the
-// call graph.
-
-class Build_connection_graphs : public Traverse
-{
- public:
-  Build_connection_graphs(Gogo* gogo)
-    : Traverse(traverse_variables
-	       | traverse_statements),
-      gogo_(gogo), dataflow_(new Dataflow), current_function_(NULL)
-  {
-    // Collect dataflow information for this program.
-    this->dataflow_->initialize(this->gogo_);
-  }
-
-  void
-  set_current_function(Named_object* function)
-  { this->current_function_ = function; }
-
-  int
-  variable(Named_object*);
-
-  int
-  statement(Block*, size_t*, Statement*);
-
-
- private:
-  // Handle a call EXPR referencing OBJECT.
-  void
-  handle_call(Named_object* object, Expression* expr);
-
-  // Get the initialization values of a composite literal EXPR.
-  Expression_list*
-  get_composite_arguments(Expression* expr);
-
-  // Handle defining OBJECT as a composite literal EXPR.
-  void
-  handle_composite_literal(Named_object* object, Expression* expr);
-
-  // Handle analysis of the left and right operands of a binary expression
-  // with respect to OBJECT.
-  void
-  handle_binary(Named_object* object, Expression* expr);
-
-  // Resolve the outermost named object of EXPR if there is one.
-  Named_object*
-  resolve_var_reference(Expression* expr);
-
-  // The IR.
-  Gogo* gogo_;
-  // The Dataflow information for this program.
-  Dataflow* dataflow_;
-  // The current function whose connection graph is being built.
-  Named_object* current_function_;
-};
-
-// Given an expression, return the outermost Named_object that it refers to.
-// This is used to model the simplification between assignments in our analysis.
-
-Named_object*
-Build_connection_graphs::resolve_var_reference(Expression* expr)
-{
-  bool done = false;
-  Expression* orig = expr;
-  while (!done)
-    {
-      // The goal of this loop is to find the variable being referenced, p,
-      // when the expression is:
-      switch (expr->classification())
-      {
-      case Expression::EXPRESSION_UNARY:
-	// &p or *p
-	expr = expr->unary_expression()->operand();
-	break;
-
-      case Expression::EXPRESSION_ARRAY_INDEX:
-	// p[i][j]
-	expr = expr->array_index_expression()->array();
-	break;
-
-      case Expression::EXPRESSION_FIELD_REFERENCE:
-	// p.i.j
-	orig = expr;
-	expr = expr->field_reference_expression()->expr();
-	break;
-
-      case Expression::EXPRESSION_RECEIVE:
-	// <- p
-	expr = expr->receive_expression()->channel();
-	break;
-
-      case Expression::EXPRESSION_BOUND_METHOD:
-	// p.c
-	expr = expr->bound_method_expression()->first_argument();
-	break;
-
-      case Expression::EXPRESSION_CALL:
-	// p.c()
-	expr = expr->call_expression()->fn();
-	break;
-
-      case Expression::EXPRESSION_TEMPORARY_REFERENCE:
-	// This is used after lowering, so try to retrieve the original
-	// expression that might have been lowered into a temporary statement.
-	expr = expr->temporary_reference_expression()->statement()->init();
-	if (expr == NULL)
-	  return NULL;
-	break;
-
-      case Expression::EXPRESSION_SET_AND_USE_TEMPORARY:
-	expr = expr->set_and_use_temporary_expression()->expression();
-	break;
-
-      case Expression::EXPRESSION_COMPOUND:
-	// p && q
-	expr = expr->compound_expression()->init();
-	break;
-
-      case Expression::EXPRESSION_CONDITIONAL:
-	// if p {
-	expr = expr->conditional_expression()->condition();
-	break;
-
-      case Expression::EXPRESSION_CONVERSION:
-	// T(p)
-	expr = expr->conversion_expression()->expr();
-	break;
-
-      case Expression::EXPRESSION_TYPE_GUARD:
-	// p.(T)
-	expr = expr->type_guard_expression()->expr();
-	break;
-
-      case Expression::EXPRESSION_UNSAFE_CONVERSION:
-	{
-	  Expression* e = expr->unsafe_conversion_expression()->expr();
-	  if (e->call_result_expression() != NULL
-	      && e->call_result_expression()->index() == 0)
-	    {
-	      // a, ok := p.(T) gets lowered into a call to one of the interface
-	      // to type conversion functions instead of a type guard expression.
-	      // We only want to make a connection between a and p, the bool
-	      // result should not escape because p escapes.
-	      e = e->call_result_expression()->call();
-
-	      Named_object* fn =
-		e->call_expression()->fn()->func_expression()->named_object();
-	      std::string fn_name = fn->name();
-	      if (fn->package() == NULL
-		  && fn->is_function_declaration()
-		  && !fn->func_declaration_value()->asm_name().empty())
-		{
-		  if (fn_name == "ifaceI2E2"
-		      || fn_name == "ifaceI2I2")
-		    e = e->call_expression()->args()->at(0);
-		  else if (fn_name == "ifaceE2I2"
-			   || fn_name == "ifaceI2I2"
-			   || fn_name == "ifaceE2T2P"
-			   || fn_name == "ifaceI2T2P"
-			   || fn_name == "ifaceE2T2"
-			   || fn_name == "ifaceI2T2")
-		    e = e->call_expression()->args()->at(1);
-		}
-	    }
-	  expr = e;
-	}
-	break;
-
-      default:
-	done = true;
-	break;
-      }
-    }
-
-  Var_expression* ve = expr->var_expression();
-  if (ve != NULL)
-    {
-      Named_object* no = ve->named_object();
-      go_assert(no->is_variable() || no->is_result_variable());
-
-      if (no->is_variable()
-	  && no->var_value()->is_closure()
-	  && this->current_function_->func_value()->needs_closure())
-	{
-	  // CURRENT_FUNCTION is a closure and NO is being set to a
-	  // variable in the enclosing function.
-	  Named_object* closure = this->current_function_;
-
-	  // If NO is a closure variable, the expression is a field
-	  // reference to the enclosed variable.
-	  Field_reference_expression* fre =
-	    orig->deref()->field_reference_expression();
-	  if (fre == NULL)
-	    return NULL;
-
-	  unsigned int closure_index = fre->field_index();
-	  no = closure->func_value()->enclosing_var(closure_index - 1);
-	}
-      return no;
-    }
-  return NULL;
-}
-
-// For a call that references OBJECT, associate the OBJECT argument with the
-// appropriate call parameter.
-
-void
-Build_connection_graphs::handle_call(Named_object* object, Expression* e)
-{
-  // Only call expression statements are interesting
-  // e.g. 'func(var)' for which we can show var does not escape.
-  Call_expression* ce = e->call_expression();
-  if (ce == NULL)
-    return;
-  else if (ce->args() == NULL)
-    {
-      if (ce->fn()->interface_field_reference_expression() != NULL)
-	{
-	  // This is a call to an interface method with no arguments. OBJECT
-	  // must be the receiver and we assume it escapes.
-	  Connection_node* rcvr_node =
-	    this->gogo_->add_connection_node(object)->connection_node();
-	  rcvr_node->set_escape_state(Node::ESCAPE_ARG);
-	}
-      return;
-    }
-  
-  // If the function call that references OBJECT is unknown, we must be
-  // conservative and assume every argument escapes.  A function call is unknown
-  // if it is a call to a function stored in a variable or a call to an
-  // interface method.
-  if (ce->fn()->func_expression() == NULL)
-    {
-      for (Expression_list::const_iterator arg = ce->args()->begin();
-	   arg != ce->args()->end();
-	   ++arg)
-	{
-	  Named_object* arg_no = this->resolve_var_reference(*arg);
-	  if (arg_no != NULL)
-	    {
-	      Connection_node* arg_node =
-		this->gogo_->add_connection_node(arg_no)->connection_node();
-	      arg_node->set_escape_state(Node::ESCAPE_ARG);
-	    }
-	  else if ((*arg)->call_expression() != NULL)
-	    this->handle_call(object, *arg);
-	}
-      return;
-    }
-
-  Named_object* callee = ce->fn()->func_expression()->named_object();
-  Function_type* fntype;
-  if (callee->is_function())
-    fntype = callee->func_value()->type();
-  else
-    fntype = callee->func_declaration_value()->type();
-
-  Node* callee_node = this->gogo_->lookup_connection_node(callee);
-  if (callee_node == NULL && callee->is_function())
-    {
-      // Might be a nested closure that hasn't been analyzed yet.
-      Named_object* currfn = this->current_function_;
-      callee_node = this->gogo_->add_connection_node(callee);
-      this->current_function_ = callee;
-      callee->func_value()->traverse(this);
-      this->current_function_ = currfn;
-    }
-
-  // First find which arguments OBJECT is to CALLEE.  Given a function call,
-  // OBJECT could be an argument multiple times e.g. CALLEE(OBJECT, OBJECT).
-  // TODO(cmang): This should be done by the Dataflow analysis so we don't have
-  // to do it each time we see a function call.  FIXME.
-  Expression_list* args = ce->args()->copy();
-  if (fntype->is_varargs()
-      && args->back()->slice_literal() != NULL)
-    {
-      // Is the function is varargs, the last argument is lowered into a slice
-      // containing all original arguments.  We want to traverse the original
-      // arguments here.
-      Slice_construction_expression* sce = args->back()->slice_literal();
-      for (Expression_list::const_iterator p = sce->vals()->begin();
-	   p != sce->vals()->end();
-	   ++p)
-	{
-	  if (*p != NULL)
-	    args->push_back(*p);
-	}
-    }
-
-  // ARG_POSITION is just a counter used to keep track of the index in the list
-  // of arguments to this call.  In a method call, the receiver will always be
-  // the first argument.  When looking at the function type, it will not be the
-  // first element in the parameter list; instead, the receiver will be
-  // non-NULL.  For convenience, mark the position of the receiver argument
-  // as negative.
-  int arg_position = fntype->is_method() ? -1 : 0;
-  std::list<int> positions;
-  for (Expression_list::const_iterator p = args->begin();
-       p != args->end();
-       ++p, ++arg_position)
-    {
-      Expression* arg = *p;
-
-      // An argument might be a chain of method calls, some of which are
-      // converted from value to pointer types.  Just remove the unary
-      // conversion if it exists.
-      if (arg->unary_expression() != NULL)
-	arg = arg->unary_expression()->operand();
-
-      // The reference to OBJECT might be in a nested call argument.
-      if (arg->call_expression() != NULL)
-	this->handle_call(object, arg);
-
-      std::vector<Named_object*> objects;
-      if (arg->is_composite_literal()
-	  || arg->heap_expression() != NULL)
-	{
-	  // For a call that has a composite literal as an argument, traverse
-	  // the initializers of the composite literal for extra objects to
-	  // associate with a parameter in this function.
-	  Expression_list* comp_args = this->get_composite_arguments(arg);
-	  if (comp_args == NULL)
-	    continue;
-
-	  for (size_t i = 0; i < comp_args->size(); ++i)
-	    {
-	      Expression* comp_arg = comp_args->at(i);
-	      if (comp_arg == NULL)
-		continue;
-	      else if (comp_arg->is_composite_literal()
-		       || comp_arg->heap_expression() != NULL)
-		{
-		  // Of course, there are situations where a composite literal
-		  // initialization value is also a composite literal.
-		  Expression_list* nested_args =
-		    this->get_composite_arguments(comp_arg);
-		  if (nested_args != NULL)
-		    comp_args->append(nested_args);
-		}
-
-	      Named_object* no = this->resolve_var_reference(comp_arg);
-	      if (no != NULL)
-		objects.push_back(no);
-	    }
-	}
-      else
-	{
-	  Named_object* arg_no = this->resolve_var_reference(arg);
-	  if (arg_no != NULL)
-	    objects.push_back(arg_no);
-	}
-
-      // There are no variables to consider for this parameter.
-      if (objects.empty())
-	continue;
-
-      for (std::vector<Named_object*>::const_iterator p1 = objects.begin();
-	   p1 != objects.end();
-	   ++p1)
-	{
-	  // If CALLEE is defined in another package and we have imported escape
-	  // information about its parameters, update the escape state of this
-	  // argument appropriately. If there is no escape information for this
-	  // function, we have to assume all arguments escape.
-	  if (callee->package() != NULL
-	      || fntype->is_builtin())
-	    {
-	      Node::Escapement_lattice param_escape = Node::ESCAPE_NONE;
-	      if (fntype->has_escape_info())
-		{
-		  if (arg_position == -1)
-		    {
-		      // Use the escape info from the receiver.
-		      param_escape = fntype->receiver_escape_state();
-		    }
-		  else if (fntype->parameters() != NULL)
-		    {
-		      const Node::Escape_states* states =
-			fntype->parameter_escape_states();
-
-		      int param_size = fntype->parameters()->size();
-		      if (arg_position >= param_size)
-			{
-			  go_assert(fntype->is_varargs());
-			  param_escape = states->back();
-			}
-		      else
-			param_escape =
-			  fntype->parameter_escape_states()->at(arg_position);
-		    }
-		}
-	      else
-		param_escape = Node::ESCAPE_ARG;
-
-	      Connection_node* arg_node =
-		this->gogo_->add_connection_node(*p1)->connection_node();
-	      if (arg_node->escape_state() > param_escape)
-		arg_node->set_escape_state(param_escape);
-	    }
-
-	  if (*p1 == object)
-	    positions.push_back(arg_position);
-	}
-    }
-
-  // If OBJECT was not found in CALLEE's arguments, OBJECT is likely a
-  // subexpression of one of the arguments e.g. CALLEE(a[OBJECT]).  This call
-  // does not give any useful information about whether OBJECT escapes.
-  if (positions.empty())
-    return;
-
-  // The idea here is to associate the OBJECT in the caller context with the
-  // parameter in the callee context.  This also needs to consider varargs.
-  // This only works with functions with arguments.
-  if (!callee->is_function())
-    return;
-
-  // Use the bindings in the callee to lookup the associated parameter.
-  const Bindings* callee_bindings = callee->func_value()->block()->bindings();
-
-  // Next find the corresponding named parameters in the function signature.
-  const Typed_identifier_list* params = fntype->parameters();
-  for (std::list<int>::const_iterator pos = positions.begin();
-       params != NULL && pos != positions.end();
-       ++pos)
-    {
-      std::string param_name;
-      if (*pos >= 0 && params->size() <= static_cast<size_t>(*pos))
-	{
-	  // There were more arguments than there are parameters. This must be
-	  // varargs and the argument corresponds to the last parameter.
-	  go_assert(fntype->is_varargs());
-	  param_name = params->back().name();
-	}
-      else if (*pos < 0)
-	{
-	  // We adjust the recorded position of method arguments by one to
-	  // account for the receiver, so *pos == -1 implies this is the
-	  // receiver and this must be a method call.
-	  go_assert(fntype->is_method() && fntype->receiver() != NULL);
-	  param_name = fntype->receiver()->name();
-	}
-      else
-	param_name = params->at(*pos).name();
-
-      if (Gogo::is_sink_name(param_name) || param_name.empty())
-	continue;
-
-      // Get the object for the associated parameter in this binding.
-      Named_object* param_no = callee_bindings->lookup_local(param_name);
-      go_assert(param_no != NULL);
-
-      // Add an edge from ARG_NODE in the caller context to the PARAM_NODE in
-      // the callee context.
-      if (object->is_variable() && object->var_value()->is_closure())
-	{
-	  int position = *pos;
-	  if (fntype->is_method())
-	    ++position;
-
-	  // Calling a function within a closure with a closure argument.
-	  // Resolve the real variable using the closure argument.
-	  object = this->resolve_var_reference(ce->args()->at(position));
-	}
-
-      Node* arg_node = this->gogo_->add_connection_node(object);
-      Node* param_node = this->gogo_->add_connection_node(param_no);
-      param_node->add_edge(arg_node);
-    }
-
-  // This is a method call with one argument: the receiver.
-  if (params == NULL)
-    {
-      go_assert(positions.size() == 1);
-      std::string rcvr_name = fntype->receiver()->name();
-      if (Gogo::is_sink_name(rcvr_name) || rcvr_name.empty())
-	return;
-
-      Named_object* rcvr_no = callee_bindings->lookup_local(rcvr_name);
-      Node* arg_node = this->gogo_->add_connection_node(object);
-      Node* rcvr_node = this->gogo_->add_connection_node(rcvr_no);
-      rcvr_node->add_edge(arg_node);
-    }
-}
-
-// Given a composite literal expression, return the initialization values.
-// This is used to handle situations where call and composite literal
-// expressions have nested composite literals as arguments/initializers.
-
-Expression_list*
-Build_connection_graphs::get_composite_arguments(Expression* expr)
-{
-  // A heap expression is just any expression that takes the address of a
-  // composite literal.
-  if (expr->heap_expression() != NULL)
-    expr = expr->heap_expression()->expr();
-
-  switch (expr->classification())
-    {
-    case Expression::EXPRESSION_STRUCT_CONSTRUCTION:
-      return expr->struct_literal()->vals();
-
-    case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION:
-      return expr->array_literal()->vals();
-
-    case Expression::EXPRESSION_SLICE_CONSTRUCTION:
-      return expr->slice_literal()->vals();
-
-    case Expression::EXPRESSION_MAP_CONSTRUCTION:
-      return expr->map_literal()->vals();
-
-    default:
-      return NULL;
-    }
-}
-
-// Given an OBJECT defined as a composite literal EXPR, create edges between
-// OBJECT and all variables referenced in EXPR.
-
-void
-Build_connection_graphs::handle_composite_literal(Named_object* object,
-						  Expression* expr)
-{
-  Expression_list* args = this->get_composite_arguments(expr);
-  if (args == NULL)
-    return;
-
-  std::vector<Named_object*> composite_args;
-  for (Expression_list::const_iterator p = args->begin();
-       p != args->end();
-       ++p)
-    {
-      if (*p == NULL)
-	continue;
-      else if ((*p)->call_expression() != NULL)
-	this->handle_call(object, *p);
-      else if ((*p)->func_expression() != NULL)
-	composite_args.push_back((*p)->func_expression()->named_object());
-      else if ((*p)->is_composite_literal()
-	       || (*p)->heap_expression() != NULL)
-	this->handle_composite_literal(object, *p);
-
-      Named_object* no = this->resolve_var_reference(*p);
-      if (no != NULL)
-	composite_args.push_back(no);
-    }
-
-  Node* object_node = this->gogo_->add_connection_node(object);
-  for (std::vector<Named_object*>::const_iterator p = composite_args.begin();
-       p != composite_args.end();
-       ++p)
-    {
-      Node* arg_node = this->gogo_->add_connection_node(*p);
-      object_node->add_edge(arg_node);
-    }
-}
-
-// Given an OBJECT reference in a binary expression E, analyze the left and
-// right operands for possible edges.
-
-void
-Build_connection_graphs::handle_binary(Named_object* object, Expression* e)
-{
-  Binary_expression* be = e->binary_expression();
-  go_assert(be != NULL);
-  Expression* left = be->left();
-  Expression* right = be->right();
-
-  if (left->call_result_expression() != NULL)
-    left = left->call_result_expression()->call();
-  if (left->call_expression() != NULL)
-    this->handle_call(object, left);
-  else if (left->binary_expression() != NULL)
-    this->handle_binary(object, left);
-  if (right->call_result_expression() != NULL)
-    right = right->call_result_expression()->call();
-  if (right->call_expression() != NULL)
-    this->handle_call(object, right);
-  else if (right->binary_expression() != NULL)
-    this->handle_binary(object, right);
-}
-
-// Create connection nodes for each variable in a called function.
-
-int
-Build_connection_graphs::variable(Named_object* var)
-{
-  Node* var_node = this->gogo_->add_connection_node(var);
-  Node* root = this->gogo_->lookup_connection_node(this->current_function_);
-  go_assert(root != NULL);
-
-  // Add VAR to the set of objects in CURRENT_FUNCTION's connection graph.
-  root->connection_node()->add_object(var_node);
-
-  // A function's results always escape.
-  if (var->is_result_variable())
-    var_node->connection_node()->set_escape_state(Node::ESCAPE_ARG);
-
-  // Create edges from a variable to its definitions.
-  const Dataflow::Defs* defs = this->dataflow_->find_defs(var);
-  if (defs != NULL)
-    {
-      for (Dataflow::Defs::const_iterator p = defs->begin();
-	   p != defs->end();
-	   ++p)
-	{
-	  Expression* def = p->val;
-	  if (def == NULL)
-	    continue;
-
-	  if (def->conversion_expression() != NULL)
-	    def = def->conversion_expression()->expr();
-	  if (def->func_expression() != NULL)
-	    {
-	      // VAR is being defined as a function object.
-	      Named_object* fn = def->func_expression()->named_object();
-	      Node* fn_node = this->gogo_->add_connection_node(fn);
-	      var_node->add_edge(fn_node);
-	    }
-	  else if(def->is_composite_literal()
-		  || def->heap_expression() != NULL)
-	    this->handle_composite_literal(var, def);
-
-	  Named_object* ref = this->resolve_var_reference(def);
-	  if (ref == NULL)
-	    continue;
-
-	  Node* ref_node = this->gogo_->add_connection_node(ref);
-	  var_node->add_edge(ref_node);
-	}
-    }
-
-  // Create edges from a reference to a variable.
-  const Dataflow::Refs* refs = this->dataflow_->find_refs(var);
-  if (refs != NULL)
-    {
-      for (Dataflow::Refs::const_iterator p = refs->begin();
-	   p != refs->end();
-	   ++p)
-	{
-	  switch (p->statement->classification())
-	  {
-	  case Statement::STATEMENT_ASSIGNMENT:
-	    {
-	      Assignment_statement* assn =
-		p->statement->assignment_statement();
-	      Named_object* lhs_no = this->resolve_var_reference(assn->lhs());
-	      Named_object* rhs_no = this->resolve_var_reference(assn->rhs());
-
-	      Expression* rhs = assn->rhs();
-	      if (rhs->is_composite_literal()
-		  || rhs->heap_expression() != NULL)
-		this->handle_composite_literal(var, rhs);
-
-	      if (rhs->call_result_expression() != NULL)
-		{
-		  // V's initialization will be a call result if
-		  // V, V1 := call(VAR).
-		  // There are no useful edges to make from V, but we want
-		  // to make sure we handle the call that references VAR.
-		  rhs = rhs->call_result_expression()->call();
-		}
-	      if (rhs->call_expression() != NULL)
-		this->handle_call(var, rhs);
-
-	      // If there is no standalone variable on the rhs, this could be a
-	      // binary expression, which isn't interesting for analysis or a
-	      // composite literal or call expression, which we handled above.
-	      // If the underlying variable on the rhs isn't VAR then it is
-	      // likely an indexing expression where VAR is the index.
-	      if(lhs_no == NULL
-		 || rhs_no == NULL
-		 || rhs_no != var)
-		break;
-
-	      Node* def_node = this->gogo_->add_connection_node(lhs_no);
-	      def_node->add_edge(var_node);
-	    }
-	    break;
-
-	  case Statement::STATEMENT_SEND:
-	    {
-	      Send_statement* send = p->statement->send_statement();
-	      Named_object* chan_no = this->resolve_var_reference(send->channel());
-	      Named_object* val_no = resolve_var_reference(send->val());
-
-	      if (chan_no == NULL || val_no == NULL)
-		break;
-
-	      Node* chan_node = this->gogo_->add_connection_node(chan_no);
-	      Node* val_node = this->gogo_->add_connection_node(val_no);
-	      chan_node->add_edge(val_node);
-	    }
-	    break;
-
-	  case Statement::STATEMENT_EXPRESSION:
-	    {
-	      Expression* call = p->statement->expression_statement()->expr();
-	      if (call->call_result_expression() != NULL)
-		call = call->call_result_expression()->call();
-	      this->handle_call(var, call);
-	    }
-	    break;
-
-	  case Statement::STATEMENT_GO:
-	  case Statement::STATEMENT_DEFER:
-	    // Any variable referenced via a go or defer statement escapes to
-	    // a different goroutine.
-	    if (var_node->connection_node()->escape_state() > Node::ESCAPE_ARG)
-	      var_node->connection_node()->set_escape_state(Node::ESCAPE_ARG);
-	    this->handle_call(var, p->statement->thunk_statement()->call());
-	    break;
-
-	  case Statement::STATEMENT_IF:
-	    {
-	      // If this is a reference via an if statement, it is interesting
-	      // if there is a function call in the condition.  References in
-	      // the then and else blocks would be discovered in an earlier
-	      // case.
-	      If_statement* if_stmt = p->statement->if_statement();
-	      Expression* cond = if_stmt->condition();
-	      if (cond->call_expression() != NULL)
-		this->handle_call(var, cond);
-	      else if (cond->binary_expression() != NULL)
-		this->handle_binary(var, cond);
-	    }
-	    break;
-
-	  case Statement::STATEMENT_VARIABLE_DECLARATION:
-	    {
-	      // VAR could be referenced as the initialization for another
-	      // variable, V e.g. V := call(VAR) or V := &T{field: VAR}.
-	      Variable_declaration_statement* decl =
-		p->statement->variable_declaration_statement();
-	      Named_object* decl_no = decl->var();
-	      Variable* v = decl_no->var_value();
-
-	      Expression* init = v->init();
-	      if (init == NULL)
-		break;
-
-	      if (init->is_composite_literal()
-		  || init->heap_expression() != NULL)
-		{
-		  // Create edges between DECL_NO and each named object in the
-		  // composite literal.
-		  this->handle_composite_literal(decl_no, init);
-		}
-
-	      if (init->call_result_expression() != NULL)
-		init = init->call_result_expression()->call();
-	      if (init->call_expression() != NULL)
-		this->handle_call(var, init);
-	      else if (init->binary_expression() != NULL)
-		this->handle_binary(var, init);
-	    }
-	    break;
-
-	  case Statement::STATEMENT_TEMPORARY:
-	    {
-	      // A call to a function with mutliple results that references VAR
-	      // will be lowered into a temporary at this point.  Make sure the
-	      // call that references VAR is handled.
-	      Expression* init = p->statement->temporary_statement()->init();
-	      if (init == NULL)
-		break;
-	      else if (init->call_result_expression() != NULL)
-		{
-		  Expression* call = init->call_result_expression()->call();
-		  this->handle_call(var, call);
-		}
-	    }
-
-	  default:
-	    break;
-	  }
-	}
-    }
-  return TRAVERSE_CONTINUE;
-}
-
-// Traverse statements to find interesting references that might have not
-// been recorded in the dataflow analysis.  For example, many statements
-// in closures are not properly recorded during dataflow analysis.  This should
-// handle all of the cases handled above in statements that reference a
-// variable.  FIXME.
-
-int
-Build_connection_graphs::statement(Block*, size_t*, Statement* s)
-{
-  switch(s->classification())
-  {
-  case Statement::STATEMENT_ASSIGNMENT:
-    {
-      Assignment_statement* assn = s->assignment_statement();
-      Named_object* lhs_no = this->resolve_var_reference(assn->lhs());
-
-      if (lhs_no == NULL)
-	break;
-
-      Expression* rhs = assn->rhs();
-      if (rhs->temporary_reference_expression() != NULL)
-	rhs = rhs->temporary_reference_expression()->statement()->init();
-      if (rhs == NULL)
-	break;
-
-      if (rhs->call_result_expression() != NULL)
-	rhs = rhs->call_result_expression()->call();
-      if (rhs->call_expression() != NULL)
-	{
-	  // It's not clear what variables we are trying to find references to
-	  // so just use the arguments to this call.
-	  Expression_list* args = rhs->call_expression()->args();
-	  if (args == NULL)
-	    break;
-
-	  for (Expression_list::const_iterator p = args->begin();
-	       p != args->end();
-	       ++p)
-	    {
-	      Named_object* no = this->resolve_var_reference(*p);
-	      if (no != NULL) {
-		Node* lhs_node = this->gogo_->add_connection_node(lhs_no);
-		Node* rhs_node = this->gogo_->add_connection_node(no);
-		lhs_node->add_edge(rhs_node);
-	      }
-	    }
-
-	  this->handle_call(lhs_no, rhs);
-	}
-      else if (rhs->func_expression() != NULL)
-	{
-	  Node* lhs_node = this->gogo_->add_connection_node(lhs_no);
-	  Named_object* fn = rhs->func_expression()->named_object();
-	  Node* fn_node = this->gogo_->add_connection_node(fn);
-	  lhs_node->add_edge(fn_node);
-	}
-      else
-	{
-	  Named_object* rhs_no = this->resolve_var_reference(rhs);
-	  if (rhs_no != NULL)
-	    {
-	      Node* lhs_node = this->gogo_->add_connection_node(lhs_no);
-	      Node* rhs_node = this->gogo_->add_connection_node(rhs_no);
-	      lhs_node->add_edge(rhs_node);
-	    }
-	}
-    }
-    break;
-
-  case Statement::STATEMENT_SEND:
-    {
-      Send_statement* send = s->send_statement();
-      Named_object* chan_no = this->resolve_var_reference(send->channel());
-      Named_object* val_no = this->resolve_var_reference(send->val());
-
-      if (chan_no == NULL || val_no == NULL)
-	break;
-
-      Node* chan_node = this->gogo_->add_connection_node(chan_no);
-      Node* val_node = this->gogo_->add_connection_node(val_no);
-      chan_node->add_edge(val_node);
-    }
-    break;
-
-  case Statement::STATEMENT_EXPRESSION:
-    {
-      Expression* expr = s->expression_statement()->expr();
-      if (expr->call_result_expression() != NULL)
-	expr = expr->call_result_expression()->call();
-      if (expr->call_expression() != NULL)
-	{
-	  // It's not clear what variables we are trying to find references to
-	  // so just use the arguments to this call.
-	  Expression_list* args = expr->call_expression()->args();
-	  if (args == NULL)
-	    break;
-
-	  for (Expression_list::const_iterator p = args->begin();
-	       p != args->end();
-	       ++p)
-	    {
-	      Named_object* no = this->resolve_var_reference(*p);
-	      if (no != NULL)
-		this->handle_call(no, expr);
-	    }
-	}
-    }
-    break;
-
-  case Statement::STATEMENT_GO:
-  case Statement::STATEMENT_DEFER:
-    {
-      // Any variable referenced via a go or defer statement escapes to
-      // a different goroutine.
-      Expression* call = s->thunk_statement()->call();
-      if (call->call_expression() != NULL)
-	{
-	  // It's not clear what variables we are trying to find references to
-	  // so just use the arguments to this call.
-	  Expression_list* args = call->call_expression()->args();
-	  if (args == NULL)
-	    break;
-
-	  for (Expression_list::const_iterator p = args->begin();
-	       p != args->end();
-	       ++p)
-	    {
-	      Named_object* no = this->resolve_var_reference(*p);
-	      if (no != NULL)
-		this->handle_call(no, call);
-	    }
-	}
-    }
-    break;
-
-  case Statement::STATEMENT_VARIABLE_DECLARATION:
-    {
-      Variable_declaration_statement* decl =
-	s->variable_declaration_statement();
-      Named_object* decl_no = decl->var();
-      Variable* v = decl_no->var_value();
-
-      Expression* init = v->init();
-      if (init == NULL)
-	break;
-
-      if (init->is_composite_literal()
-	  || init->heap_expression() != NULL)
-	{
-	  // Create edges between DECL_NO and each named object in the
-	  // composite literal.
-	  this->handle_composite_literal(decl_no, init);
-	}
-
-      if (init->call_result_expression() != NULL)
-	init = init->call_result_expression()->call();
-      if (init->call_expression() != NULL)
-	{
-	  // It's not clear what variables we are trying to find references to
-	  // so just use the arguments to this call.
-	  Expression_list* args = init->call_expression()->args();
-	  if (args == NULL)
-	    break;
-
-	  for (Expression_list::const_iterator p = args->begin();
-	       p != args->end();
-	       ++p)
-	    {
-	      Named_object* no = this->resolve_var_reference(*p);
-	      if (no != NULL)
-		this->handle_call(no, init);
-	    }
-	}
-    }
-    break;
-
-  default:
-    break;
-  }
-
-  return TRAVERSE_CONTINUE;
-}
-
-// Build the connection graphs for each function present in the call graph.
-
-void
-Gogo::build_connection_graphs()
-{
-  Build_connection_graphs build_conns(this);
-
-  for (std::set<Node*>::const_iterator p = this->call_graph_.begin();
-       p != this->call_graph_.end();
-       ++p)
-    {
-      Named_object* func = (*p)->object();
-      
-      go_assert(func->is_function() || func->is_function_declaration());
-      Function_type* fntype;
-      if (func->is_function())
-	fntype = func->func_value()->type();
-      else
-	fntype = func->func_declaration_value()->type();
-      if (fntype->is_builtin())
-	continue;
-
-      this->add_connection_node(func);
-      build_conns.set_current_function(func);
-      if (func->is_function())
-	{
-	  // A pointer receiver of a method always escapes from the method.
-	  if (fntype->is_method() &&
-	      fntype->receiver()->type()->points_to() != NULL)
-	    {
-	      const Bindings* callee_bindings =
-		func->func_value()->block()->bindings();
-	      std::string rcvr_name = fntype->receiver()->name();
-	      if (Gogo::is_sink_name(rcvr_name) || rcvr_name.empty())
-		return;
-
-	      Named_object* rcvr_no = callee_bindings->lookup_local(rcvr_name);
-	      Node* rcvr_node = this->add_connection_node(rcvr_no);
-	      rcvr_node->connection_node()->set_escape_state(Node::ESCAPE_ARG);
-	    }
-	  func->func_value()->traverse(&build_conns);
-	}
-    }
-}
-
-void
-Gogo::analyze_reachability()
-{
-  std::list<Node*> worklist;
-
-  // Run reachability analysis on all globally escaping objects.
-  for (std::set<Node*>::const_iterator p = this->global_connections_.begin();
-       p != this->global_connections_.end();
-       ++p)
-    worklist.push_back(*p);
-
-  while (!worklist.empty())
-    {
-      Node* m = worklist.front();
-      worklist.pop_front();
-
-      std::set<Node*> reachable = m->edges();
-      if (m->object()->is_function()
-	  && m->object()->func_value()->needs_closure())
-	{
-	  // If a closure escapes everything it closes over also escapes.
-	  Function* closure = m->object()->func_value();
-	  for (size_t i = 0; i < closure->closure_field_count(); i++)
-	    {
-	      Named_object* enclosed = closure->enclosing_var(i);
-	      Node* enclosed_node = this->lookup_connection_node(enclosed);
-	      go_assert(enclosed_node != NULL);
-	      reachable.insert(enclosed_node);
-	    }
-	}
-      for (std::set<Node*>::iterator n = reachable.begin();
-	   n != reachable.end();
-	   ++n)
-	{
-	  // If an object can be reached from a node with ESCAPE_GLOBAL,
-	  // it also must ESCAPE_GLOBAL.
-	  if ((*n)->connection_node()->escape_state() != Node::ESCAPE_GLOBAL)
-	    {
-	      (*n)->connection_node()->set_escape_state(Node::ESCAPE_GLOBAL);
-	      worklist.push_back(*n);
-	    }
-	}
-    }
-
-  // Run reachability analysis on all objects that escape via arguments.
-  for (Named_escape_nodes::const_iterator p =
-	 this->named_connection_nodes_.begin();
-       p != this->named_connection_nodes_.end();
-       ++p)
-    {
-      if (p->second->connection_node()->escape_state() < Node::ESCAPE_NONE)
-	worklist.push_back(p->second);
-    }
-
-  while (!worklist.empty())
-    {
-      Node* m = worklist.front();
-      worklist.pop_front();
-
-      std::set<Node*> reachable = m->edges();
-      if (m->object()->is_function()
-	  && m->object()->func_value()->needs_closure())
-	{
-	  // If a closure escapes everything it closes over also escapes.
-	  Function* closure = m->object()->func_value();
-	  for (size_t i = 0; i < closure->closure_field_count(); i++)
-	    {
-	      Named_object* enclosed = closure->enclosing_var(i);
-	      Node* enclosed_node = this->lookup_connection_node(enclosed);
-	      go_assert(enclosed_node != NULL);
-	      reachable.insert(enclosed_node);
-	    }
-	}
-      for (std::set<Node*>::iterator n = reachable.begin();
-	   n != reachable.end();
-	   ++n)
-	{
-	  // If an object can be reached from a node with ESCAPE_ARG,
-	  // it is ESCAPE_ARG or ESCAPE_GLOBAL.
-	  Node::Escapement_lattice e = m->connection_node()->escape_state();
-	  if ((*n)->connection_node()->escape_state() > e)
-	    {
-	      (*n)->connection_node()->set_escape_state(e);
-	      worklist.push_back(*n);
-	    }
-	}
-    }  
-}
-
-// Iterate over all functions analyzed in the analysis, recording escape
-// information for each receiver and parameter.
-
-void
-Gogo::mark_escaping_signatures()
-{
-  for (std::set<Node*>::const_iterator p = this->call_graph_.begin();
-       p != this->call_graph_.end();
-       ++p)
-    {
-      Named_object* fn = (*p)->object();
-      if (!fn->is_function())
-	continue;
-
-      Function* func = fn->func_value();
-      Function_type* fntype = func->type();
-      const Bindings* bindings = func->block()->bindings();
-
-      // If this is a method, set the escape state of the receiver.
-      if (fntype->is_method())
-	{
-	  std::string rcvr_name = fntype->receiver()->name();
-	  if (rcvr_name.empty() || Gogo::is_sink_name(rcvr_name))
-	    fntype->set_receiver_escape_state(Node::ESCAPE_NONE);
-	  else
-	    {
-	      Named_object* rcvr_no = bindings->lookup_local(rcvr_name);
-	      go_assert(rcvr_no != NULL);
-
-	      Node* rcvr_node = this->lookup_connection_node(rcvr_no);
-	      if (rcvr_node != NULL)
-		{
-		  Node::Escapement_lattice e =
-		    rcvr_node->connection_node()->escape_state();
-		  fntype->set_receiver_escape_state(e);
-		}
-	      else
-		fntype->set_receiver_escape_state(Node::ESCAPE_NONE);
-	    }
-	  fntype->set_has_escape_info();
-	}
-
-      const Typed_identifier_list* params = fntype->parameters();
-      if (params == NULL)
-	continue;
-
-      fntype->set_has_escape_info();
-      Node::Escape_states* param_escape_states = new Node::Escape_states;
-      for (Typed_identifier_list::const_iterator p1 = params->begin();
-	   p1 != params->end();
-	   ++p1)
-	{
-	  std::string param_name = p1->name();
-	  if (param_name.empty() || Gogo::is_sink_name(param_name))
-	    param_escape_states->push_back(Node::ESCAPE_NONE);
-	  else
-	    {
-	      Named_object* param_no = bindings->lookup_local(param_name);
-	      go_assert(param_no != NULL);
-
-	      Node* param_node = this->lookup_connection_node(param_no);
-	      if (param_node == NULL)
-		{
-		  param_escape_states->push_back(Node::ESCAPE_NONE);
-		  continue;
-		}
-
-	      Node::Escapement_lattice e =
-		param_node->connection_node()->escape_state();
-	      param_escape_states->push_back(e);
-	    }
-	}
-      go_assert(params->size() == param_escape_states->size());
-      fntype->set_parameter_escape_states(param_escape_states);
-    }
-}
-
-class Optimize_allocations : public Traverse
-{
- public:
-  Optimize_allocations(Gogo* gogo)
-    : Traverse(traverse_variables),
-      gogo_(gogo)
-  { }
-
-  int
-  variable(Named_object*);
-
- private:
-  // The IR.
-  Gogo* gogo_;
-};
-
-// The -fgo-optimize-alloc flag activates this escape analysis.
-
-Go_optimize optimize_allocation_flag("allocs");
-
-// Propagate escape information for each variable.
-
-int
-Optimize_allocations::variable(Named_object* var)
-{
-  Node* var_node = this->gogo_->lookup_connection_node(var);
-  if (var_node == NULL
-      || var_node->connection_node()->escape_state() != Node::ESCAPE_NONE)
-    return TRAVERSE_CONTINUE;
-
-  if (var->is_variable())
-    {
-      var->var_value()->set_does_not_escape();
-      if (var->var_value()->init() != NULL
-	  && var->var_value()->init()->allocation_expression() != NULL)
-	{
-	  Allocation_expression* alloc =
-	    var->var_value()->init()->allocation_expression();
-	  alloc->set_allocate_on_stack();
-	}
-    }
-
-  return TRAVERSE_CONTINUE;
-}
-
-// Perform escape analysis on this program and optimize allocations using
-// the derived information if -fgo-optimize-allocs.
-
-void
-Gogo::optimize_allocations(const char** filenames)
-{
-  if (!::optimize_allocation_flag.is_enabled() || saw_errors())
-    return;
-
-  // Build call graph for this program.
-  this->build_call_graph();
-
-  // Dump the call graph for this program if -fgo-dump-calls is enabled.
-  this->dump_call_graph(filenames[0]);
-
-  // Build the connection graphs for this program.
-  this->build_connection_graphs();
-
-  // Dump the connection graphs if -fgo-dump-connections is enabled.
-  this->dump_connection_graphs(filenames[0]);
-
-  // Given the connection graphs for this program, perform a reachability
-  // analysis to determine what objects escape.
-  this->analyze_reachability();
-
-  // Propagate escape information to variables and variable initializations.
-  Optimize_allocations optimize_allocs(this);
-  this->traverse(&optimize_allocs);
-
-  // Store escape information for a function's receivers and parameters in the
-  // function's signature for use when exporting package information.
-  this->mark_escaping_signatures();
-}
Index: gcc/go/gofrontend/escape.h
===================================================================
--- gcc/go/gofrontend/escape.h	(revision 234304)
+++ gcc/go/gofrontend/escape.h	(working copy)
@@ -1,310 +0,0 @@ 
-// escape.h -- Go frontend escape analysis.     -*- C++ -*-
-
-// Copyright 2015 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_ESCAPE_H
-#define GO_ESCAPE_H
-
-#include "go-system.h"
-#include "string-dump.h"
-
-class Call_node;
-class Connection_node;
-class Connection_dump_context;
-class Gogo;
-class Named_object;
-
-// A basic escape analysis implementation for the Go frontend based on the
-// algorithm from "Escape Analysis for Java" by Choi et. al in OOPSLA '99.
-// This is a simplified version of the flow insensitive analysis with the goal
-// of reducing the overhead cost of garbage collection by allocating objects
-// on the stack when they do not escape the function they were created in.
-//
-// A major simplification is that the analysis only implements what Choi refers
-// to as "deferred edges" which are used to used model assignments that copy
-// references from one variable to another e.g. a := b.  It is unnecessary to
-// consider assignments to the fields of an object because, in general, if a
-// field of an object escapes and must be heap-allocated, there is no way to
-// heap-allocate that escaping field without heap-allocating the entire object.
-// That is, for some globally escaping object GVAR, if there is an assignment
-// of the form GVAR = t.f such that field f of object t escapes, it is likely
-// that t must be heap-allocated as well.  In the analysis, this assignment
-// will be simplified to GVAR = t, which is imprecise but has the same effect.
-
-// This is a general graph node representing a named object used in a call graph
-// or connection graph.  In a call graph, each named object is either a Function
-// or Function_declaration representing a function called during the program
-// execution (which isn't necessarily every function declared).  In a connection
-// graph, there is a node for each node in the call graph, which forms the root
-// of that connection graph.  Each connection graph root contains nodes whose
-// objects are either variables used in the function defintion or are nested
-// closures created within the function definition.  The connection graph is
-// a way of modeling the connectivity between all objects created in a given
-// function as well as understanding the relationship between input arguments
-// in the caller and the formal parameters in the callee.
-
-class Node
-{
- public:
-  enum Node_classification
-  {
-    NODE_CALL,
-    NODE_CONNECTION
-  };
-
-  virtual ~Node();
-
-  // Make a call node for FUNCTION.
-  static Node*
-  make_call(Named_object* function);
-
-  // Make a connection node for OBJECT.
-  // Note: values in this enum appear in export data, and therefore MUST NOT
-  // change.
-  enum Escapement_lattice
-  {
-    // ESCAPE_GLOBAL means that the object escapes all functions globally.
-    ESCAPE_GLOBAL = 0,
-    // ESCAPE_ARG with respect to a function means that the object escapes that
-    // function it is created in via the function's arguments or results.
-    ESCAPE_ARG = 1,
-    // ESCAPE_NONE means that the object does not escape the function in which
-    // it was created.
-    ESCAPE_NONE = 2
-  };
-
-  // A list of states usually corresponding to a list of function parameters.
-  typedef std::vector<Escapement_lattice> Escape_states;
-
-  static Node*
-  make_connection(Named_object* object, Escapement_lattice e);
-
-  // Return the node classification.
-  Node_classification
-  classification() const
-  { return this->classification_; }
-
-  // Return whether this is a call node.
-  bool
-  is_call() const
-  { return this->classification_ == NODE_CALL; }
-
-  // Return whether this is a connection node.
-  bool
-  is_connection() const
-  { return this->classification_ == NODE_CONNECTION; }
-
-  // If this is a connection node, return the Connection_node.
-  // Otherwise, return NULL.
-  Connection_node*
-  connection_node()
-  { return this->convert<Connection_node, NODE_CONNECTION>(); }
-
-  // Return this node's unique id.
-  unsigned int
-  id() const
-  { return this->id_; }
-
-  // Return this node's generated name for GraphViz.
-  virtual const std::string&
-  name() = 0;
-
-  // Return this node's generated label for GraphViz.
-  virtual const std::string&
-  label();
-
-  // Return the object this node represents.
-  Named_object*
-  object() const
-  { return this->object_; }
-
-  void
-  add_edge(Node* v)
-  { this->edges_.insert(v); }
-
-  const std::set<Node*>&
-  edges() const
-  { return this->edges_; }
-
- protected:
-  Node(Node_classification, Named_object* object);
-
-  const std::string&
-  get_name() const
-  { return this->name_; }
-
-  void
-  set_name(const std::string& name)
-  { this->name_ = name; }
-
-  const std::string&
-  get_label() const
-  { return this->label_; }
-
-  void
-  set_label(const std::string& label)
-  { this->label_ = label; }
-
- private:
-  template<typename Node_class,
-	   Node_classification node_classification>
-  const Node_class*
-  convert() const
-  {
-    return (this->classification_ == node_classification
-	    ? static_cast<const Node_class*>(this)
-	    : NULL);
-  }
-
-  template<typename Node_class,
-	   Node_classification node_classification>
-  Node_class*
-  convert()
-  {
-    return (this->classification_ == node_classification
-	    ? static_cast<Node_class*>(this)
-	    : NULL);
-  }
-
-  // The classification of this node.
-  Node_classification classification_;
-  // A unique ID for this node.
-  unsigned int id_;
-  // The name for this node e.g. "Node<ID>" used as a GraphViz identifier.
-  std::string name_;
-  // The label for this node in the GraphViz representation.
-  std::string label_;
-  // The object represented by this node.
-  Named_object* object_;
-  // A distinct set of nodes that this node has edges to.
-  std::set<Node*> edges_;
-};
-
-
-// A node representing a function that might be called during program execution.
-
-class Call_node : public Node
-{
- public:
-  Call_node(Named_object* function);
-
-  const std::string&
-  name();
-};
-
-// A node representing an object in the connection graph built for each function
-// in the call graph.
-
-class Connection_node : public Node
-{
- public:
-  Connection_node(Named_object* object, Escapement_lattice e)
-    : Node(NODE_CONNECTION, object),
-      escape_state_(e)
-  { }
-
-  // Return this node's generated name for GraphViz.
-  const std::string&
-  name();
-
-  // Return this node's generated label for GraphViz.
-  const std::string&
-  label();
-
-  // Return the escape state for this node.
-  Escapement_lattice
-  escape_state() const
-  { return this->escape_state_; }
-
-  // Set the escape state for this node.
-  void
-  set_escape_state(Escapement_lattice e)
-  { this->escape_state_ = e; }
-
-  // Return the objects inside of this connection graph.
-  // This is empty for all connection nodes that are not the root of a
-  // connection graph.  Each node in the call graph is a root of a connection
-  // graph.
-  const std::set<Node*>&
-  objects() const
-  { return this->objects_; }
-
-  void
-  add_object(Node* object)
-  { this->objects_.insert(object); }
-
-  void
-  dump_connection(Connection_dump_context*);
-
- private:
-  // The escapement of this node.
-  Escapement_lattice escape_state_;
-  // The set of nodes contained within this connection node.  If this node is
-  // not a root of a connection graph, this will be empty.
-  std::set<Node*> objects_;
-};
-
-// This class implements fgo-dump-calls. The Call graph dump of a Go program.
-
-class Call_dump_context : public String_dump
-{
- public:
-  Call_dump_context(std::ostream* out = NULL);
-
-  // Initialize the dump context.
-  void
-  dump(Gogo*, const char* basename);
-
-  // Get dump output stream.
-  std::ostream&
-  ostream()
-  { return *this->ostream_; }
-
-  // Implementation of String_dump interface.
-  void
-  write_c_string(const char*);
-
-  void
-  write_string(const std::string&);
-
- private:
-  // Stream on output dump file.
-  std::ostream* ostream_;
-
-  Gogo* gogo_;
-};
-
-// This class implements fgo-dump-conns.  The connection graph dump of
-// the functions called in a Go program.
-
-class Connection_dump_context : public String_dump
-{
- public:
-  Connection_dump_context(std::ostream* out = NULL);
-
-  // Initialize the dump context.
-  void
-  dump(Gogo*, const char* basename);
-
-  // Get dump output stream.
-  std::ostream&
-  ostream()
-  { return *this->ostream_; }
-
-  // Implementation of String_dump interface.
-  void
-  write_c_string(const char*);
-
-  void
-  write_string(const std::string&);
-
- private:
-  // Stream on output dump file.
-  std::ostream* ostream_;
-
-  Gogo* gogo_;
-};
-
-#endif // !defined(GO_ESCAPE_H)
Index: gcc/go/gofrontend/export.cc
===================================================================
--- gcc/go/gofrontend/export.cc	(revision 234304)
+++ gcc/go/gofrontend/export.cc	(working copy)
@@ -436,17 +436,6 @@  Export::write_type(const Type* type)
     this->type_refs_[type] = index;
 }
 
-// Export escape information.
-
-void
-Export::write_escape(const Node::Escapement_lattice& e)
-{
-  char buf[30];
-  snprintf(buf, sizeof buf, "<escape %d>", e);
-  this->write_c_string(buf);
-  return;
-}
-
 // Add the builtin types to the export table.
 
 void
Index: gcc/go/gofrontend/export.h
===================================================================
--- gcc/go/gofrontend/export.h	(revision 234304)
+++ gcc/go/gofrontend/export.h	(working copy)
@@ -7,7 +7,6 @@ 
 #ifndef GO_EXPORT_H
 #define GO_EXPORT_H
 
-#include "escape.h"
 #include "string-dump.h"
 
 struct sha1_ctx;
@@ -162,10 +161,6 @@  class Export : public String_dump
   void
   write_type(const Type*);
 
-  // Write out escape information.
-  void
-  write_escape(const Node::Escapement_lattice& e);
-
  private:
   Export(const Export&);
   Export& operator=(const Export&);
Index: gcc/go/gofrontend/go.cc
===================================================================
--- gcc/go/gofrontend/go.cc	(revision 234304)
+++ gcc/go/gofrontend/go.cc	(working copy)
@@ -110,10 +110,6 @@  go_parse_input_files(const char** filena
   if (only_check_syntax)
     return;
 
-  // Consider escape analysis information when deciding if a variable should
-  // live on the heap or on the stack.
-  ::gogo->optimize_allocations(filenames);
-
   // Export global identifiers as appropriate.
   ::gogo->do_exports();
 
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 234304)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -18,7 +18,6 @@ 
 #include "runtime.h"
 #include "import.h"
 #include "export.h"
-#include "escape.h"
 #include "backend.h"
 #include "gogo.h"
 
@@ -156,19 +155,11 @@  Gogo::Gogo(Backend* backend, Linemap* li
   Function_type* new_type = Type::make_function_type(NULL, NULL, NULL, loc);
   new_type->set_is_varargs();
   new_type->set_is_builtin();
-  Node::Escape_states* new_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_NONE);
-  new_type->set_parameter_escape_states(new_escapes);
-  new_type->set_has_escape_info();
   this->globals_->add_function_declaration("new", NULL, new_type, loc);
 
   Function_type* make_type = Type::make_function_type(NULL, NULL, NULL, loc);
   make_type->set_is_varargs();
   make_type->set_is_builtin();
-  Node::Escape_states* make_escapes =
-    new Node::Escape_states(2, Node::ESCAPE_NONE);
-  make_type->set_parameter_escape_states(make_escapes);
-  make_type->set_has_escape_info();
   this->globals_->add_function_declaration("make", NULL, make_type, loc);
 
   Typed_identifier_list* len_result = new Typed_identifier_list();
@@ -176,10 +167,6 @@  Gogo::Gogo(Backend* backend, Linemap* li
   Function_type* len_type = Type::make_function_type(NULL, NULL, len_result,
 						     loc);
   len_type->set_is_builtin();
-  Node::Escape_states* len_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_NONE);
-  len_type->set_parameter_escape_states(len_escapes);
-  len_type->set_has_escape_info();
   this->globals_->add_function_declaration("len", NULL, len_type, loc);
 
   Typed_identifier_list* cap_result = new Typed_identifier_list();
@@ -187,26 +174,16 @@  Gogo::Gogo(Backend* backend, Linemap* li
   Function_type* cap_type = Type::make_function_type(NULL, NULL, len_result,
 						     loc);
   cap_type->set_is_builtin();
-  Node::Escape_states* cap_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_NONE);
-  cap_type->set_parameter_escape_states(cap_escapes);
-  cap_type->set_has_escape_info();
   this->globals_->add_function_declaration("cap", NULL, cap_type, loc);
 
   Function_type* print_type = Type::make_function_type(NULL, NULL, NULL, loc);
   print_type->set_is_varargs();
   print_type->set_is_builtin();
-  Node::Escape_states* print_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_NONE);
-  print_type->set_parameter_escape_states(print_escapes);
-  print_type->set_has_escape_info();
   this->globals_->add_function_declaration("print", NULL, print_type, loc);
 
   print_type = Type::make_function_type(NULL, NULL, NULL, loc);
   print_type->set_is_varargs();
   print_type->set_is_builtin();
-  print_type->set_parameter_escape_states(print_escapes);
-  print_type->set_has_escape_info();
   this->globals_->add_function_declaration("println", NULL, print_type, loc);
 
   Type *empty = Type::make_empty_interface_type(loc);
@@ -215,10 +192,6 @@  Gogo::Gogo(Backend* backend, Linemap* li
   Function_type *panic_type = Type::make_function_type(NULL, panic_parms,
 						       NULL, loc);
   panic_type->set_is_builtin();
-  Node::Escape_states* panic_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_ARG);
-  panic_type->set_parameter_escape_states(panic_escapes);
-  panic_type->set_has_escape_info();
   this->globals_->add_function_declaration("panic", NULL, panic_type, loc);
 
   Typed_identifier_list* recover_result = new Typed_identifier_list();
@@ -232,10 +205,6 @@  Gogo::Gogo(Backend* backend, Linemap* li
   Function_type* close_type = Type::make_function_type(NULL, NULL, NULL, loc);
   close_type->set_is_varargs();
   close_type->set_is_builtin();
-  Node::Escape_states* close_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_NONE);
-  close_type->set_parameter_escape_states(close_escapes);
-  close_type->set_has_escape_info();
   this->globals_->add_function_declaration("close", NULL, close_type, loc);
 
   Typed_identifier_list* copy_result = new Typed_identifier_list();
@@ -244,56 +213,31 @@  Gogo::Gogo(Backend* backend, Linemap* li
 						      copy_result, loc);
   copy_type->set_is_varargs();
   copy_type->set_is_builtin();
-  Node::Escape_states* copy_escapes =
-    new Node::Escape_states(2, Node::ESCAPE_NONE);
-  copy_type->set_parameter_escape_states(copy_escapes);
-  copy_type->set_has_escape_info();
   this->globals_->add_function_declaration("copy", NULL, copy_type, loc);
 
   Function_type* append_type = Type::make_function_type(NULL, NULL, NULL, loc);
   append_type->set_is_varargs();
   append_type->set_is_builtin();
-  Node::Escape_states* append_escapes = new Node::Escape_states;
-  append_escapes->push_back(Node::ESCAPE_ARG);
-  append_escapes->push_back(Node::ESCAPE_NONE);
-  append_type->set_parameter_escape_states(append_escapes);
-  append_type->set_has_escape_info();
   this->globals_->add_function_declaration("append", NULL, append_type, loc);
 
   Function_type* complex_type = Type::make_function_type(NULL, NULL, NULL, loc);
   complex_type->set_is_varargs();
   complex_type->set_is_builtin();
-  Node::Escape_states* complex_escapes =
-    new Node::Escape_states(2, Node::ESCAPE_NONE);
-  complex_type->set_parameter_escape_states(complex_escapes);
-  complex_type->set_has_escape_info();
   this->globals_->add_function_declaration("complex", NULL, complex_type, loc);
 
   Function_type* real_type = Type::make_function_type(NULL, NULL, NULL, loc);
   real_type->set_is_varargs();
   real_type->set_is_builtin();
-  Node::Escape_states* real_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_NONE);
-  real_type->set_parameter_escape_states(real_escapes);
-  real_type->set_has_escape_info();
   this->globals_->add_function_declaration("real", NULL, real_type, loc);
 
   Function_type* imag_type = Type::make_function_type(NULL, NULL, NULL, loc);
   imag_type->set_is_varargs();
   imag_type->set_is_builtin();
-  Node::Escape_states* imag_escapes =
-    new Node::Escape_states(1, Node::ESCAPE_NONE);
-  imag_type->set_parameter_escape_states(imag_escapes);
-  imag_type->set_has_escape_info();
   this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
 
   Function_type* delete_type = Type::make_function_type(NULL, NULL, NULL, loc);
   delete_type->set_is_varargs();
   delete_type->set_is_builtin();
-  Node::Escape_states* delete_escapes =
-    new Node::Escape_states(2, Node::ESCAPE_NONE);
-  delete_type->set_parameter_escape_states(delete_escapes);
-  delete_type->set_has_escape_info();
   this->globals_->add_function_declaration("delete", NULL, delete_type, loc);
 }
 
@@ -1889,74 +1833,6 @@  Gogo::add_label_reference(const std::str
 				   issue_goto_errors);
 }
 
-// Add a function to the call graph.
-
-Node*
-Gogo::add_call_node(Named_object* function)
-{
-  Node* call = this->lookup_call_node(function);
-  if (call == NULL)
-    {
-      call = Node::make_call(function);
-      this->call_graph_.insert(call);
-      this->named_call_nodes_[function] = call;
-    }
-  return call;
-}
-
-// Find the call node that represents FUNCTION.  Return NULL if it does not
-// exist.
-
-Node*
-Gogo::lookup_call_node(Named_object* function) const
-{
-  Named_escape_nodes::const_iterator p = this->named_call_nodes_.find(function);
-  if (p == this->named_call_nodes_.end())
-    return NULL;
-  return p->second;
-}
-
-// Add a connection node for OBJECT.
-
-Node*
-Gogo::add_connection_node(Named_object* object)
-{
-  Node* connection = this->lookup_connection_node(object);
-  if (connection == NULL)
-    {
-      connection = Node::make_connection(object, Node::ESCAPE_NONE);
-
-      // Each global variable is a part of the global connection graph.
-      if (object->is_variable()
-	  && object->var_value()->is_global())
-	{
-	  connection->connection_node()->set_escape_state(Node::ESCAPE_GLOBAL);
-	  this->global_connections_.insert(connection);
-	}
-
-      // Each function declaration or definition is the root of its own
-      // connection graph.  This means closures will have their own
-      // connection graph that objects in the enclosing function might
-      // refer to.
-      if (object->is_function() || object->is_function_declaration())
-	this->connection_roots_.insert(connection);
-      this->named_connection_nodes_[object] = connection;
-    }
-  return connection;
-}
-
-// Find the connection node for OBJECT.  Return NULL if it does not exist.
-
-Node*
-Gogo::lookup_connection_node(Named_object* object) const
-{
-  Named_escape_nodes::const_iterator p =
-    this->named_connection_nodes_.find(object);
-  if (p == this->named_connection_nodes_.end())
-    return NULL;
-  return p->second;
-}
-
 // Return the current binding state.
 
 Bindings_snapshot*
@@ -4918,13 +4794,6 @@  Function::export_func_with_type(Export*
       exp->write_c_string("(");
       const Typed_identifier* receiver = fntype->receiver();
       exp->write_name(receiver->name());
-
-      if (fntype->has_escape_info())
-        {
-          exp->write_c_string(" ");
-          exp->write_escape(fntype->receiver_escape_state());
-        }
-
       exp->write_c_string(" ");
       exp->write_type(receiver->type());
       exp->write_c_string(") ");
@@ -4948,13 +4817,6 @@  Function::export_func_with_type(Export*
 	  else
 	    exp->write_c_string(", ");
 	  exp->write_name(p->name());
-
-	  if (fntype->has_escape_info())
-	    {
-	      exp->write_c_string(" ");
-	      exp->write_escape(fntype->parameter_escape_states()->at(i));
-	    }
-
 	  exp->write_c_string(" ");
 	  if (!is_varargs || p + 1 != parameters->end())
 	    exp->write_type(p->type());
@@ -5002,29 +4864,17 @@  Function::export_func_with_type(Export*
 void
 Function::import_func(Import* imp, std::string* pname,
 		      Typed_identifier** preceiver,
-		      Node::Escapement_lattice* rcvr_escape,
 		      Typed_identifier_list** pparameters,
-		      Node::Escape_states** pparam_escapes,
 		      Typed_identifier_list** presults,
-		      bool* is_varargs, bool* has_escape_info)
+		      bool* is_varargs)
 {
-  *has_escape_info = false;
-
   imp->require_c_string("func ");
 
   *preceiver = NULL;
-  *rcvr_escape = Node::ESCAPE_NONE;
   if (imp->peek_char() == '(')
     {
       imp->require_c_string("(");
       std::string name = imp->read_name();
-
-      if (imp->match_c_string(" <escape")){
-	*has_escape_info = true;
-	imp->require_c_string(" ");
-	*rcvr_escape = imp->read_escape_info();
-      }
-
       imp->require_c_string(" ");
       Type* rtype = imp->read_type();
       *preceiver = new Typed_identifier(name, rtype, imp->location());
@@ -5034,27 +4884,16 @@  Function::import_func(Import* imp, std::
   *pname = imp->read_identifier();
 
   Typed_identifier_list* parameters;
-  Node::Escape_states* param_escapes;
   *is_varargs = false;
   imp->require_c_string(" (");
   if (imp->peek_char() == ')')
-    {
-      parameters = NULL;
-      param_escapes = NULL;
-    }
+    parameters = NULL;
   else
     {
       parameters = new Typed_identifier_list();
-      param_escapes = new Node::Escape_states();
       while (true)
 	{
 	  std::string name = imp->read_name();
-	  if (imp->match_c_string(" <escape")){
-	    *has_escape_info = true;
-	    imp->require_c_string(" ");
-	    param_escapes->push_back(imp->read_escape_info());
-	  }
-
 	  imp->require_c_string(" ");
 
 	  if (imp->match_c_string("..."))
@@ -5076,7 +4915,6 @@  Function::import_func(Import* imp, std::
     }
   imp->require_c_string(")");
   *pparameters = parameters;
-  *pparam_escapes = param_escapes;
 
   Typed_identifier_list* results;
   if (imp->peek_char() != ' ')
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 234304)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -7,7 +7,6 @@ 
 #ifndef GO_GOGO_H
 #define GO_GOGO_H
 
-#include "escape.h"
 #include "go-linemap.h"
 
 class Traverse;
@@ -126,21 +125,6 @@  class Gogo
   linemap()
   { return this->linemap_; }
 
-  // Get the Call Graph.
-  const std::set<Node*>&
-  call_graph() const
-  { return this->call_graph_; }
-
-  // Get the roots of each connection graph.
-  const std::set<Node*>&
-  connection_roots() const
-  { return this->connection_roots_; }
-
-  // Get the nodes that escape globally.
-  const std::set<Node*>&
-  global_connections() const
-  { return this->global_connections_; }
-
   // Get the package name.
   const std::string&
   package_name() const;
@@ -361,22 +345,6 @@  class Gogo
   add_label_reference(const std::string&, Location,
 		      bool issue_goto_errors);
 
-  // Add a FUNCTION to the call graph.
-  Node*
-  add_call_node(Named_object* function);
-
-  // Lookup the call node for FUNCTION.
-  Node*
-  lookup_call_node(Named_object* function) const;
-
-  // Add a connection node for OBJECT.
-  Node*
-  add_connection_node(Named_object* object);
-
-  // Lookup the connection node for OBJECT.
-  Node*
-  lookup_connection_node(Named_object* object) const;
-
   // Return a snapshot of the current binding state.
   Bindings_snapshot*
   bindings_snapshot(Location);
@@ -576,26 +544,6 @@  class Gogo
   void
   check_return_statements();
 
-  // Build call graph.
-  void
-  build_call_graph();
-
-  // Build connection graphs.
-  void
-  build_connection_graphs();
-
-  // Analyze reachability in the connection graphs.
-  void
-  analyze_reachability();
-
-  // Record escape information in function signatures for export data.
-  void
-  mark_escaping_signatures();
-
-  // Optimize variable allocation.
-  void
-  optimize_allocations(const char** filenames);
-
   // Do all exports.
   void
   do_exports();
@@ -730,10 +678,6 @@  class Gogo
   // where they were defined.
   typedef Unordered_map(std::string, Location) File_block_names;
 
-  // Type used to map named objects that refer to objects to the
-  // node that represent them in the escape analysis graphs.
-  typedef Unordered_map(Named_object*, Node*)  Named_escape_nodes;
-
   // Type used to queue writing a type specific function.
   struct Specific_type_function
   {
@@ -766,20 +710,6 @@  class Gogo
   // The global binding contour.  This includes the builtin functions
   // and the package we are compiling.
   Bindings* globals_;
-  // The call graph for a program execution which represents the functions
-  // encountered and the caller-callee relationship between the functions.
-  std::set<Node*> call_graph_;
-  // The nodes that form the roots of the connection graphs for each called
-  // function and represent the connectivity relationship between all objects
-  // in the function.
-  std::set<Node*> connection_roots_;
-  // All connection nodes that have an escape state of ESCAPE_GLOBAL are a part
-  // of a special connection graph of only global variables.
-  std::set<Node*> global_connections_;
-  // Mapping from named objects to nodes in the call graph.
-  Named_escape_nodes named_call_nodes_;
-  // Mapping from named objects to nodes in a connection graph.
-  Named_escape_nodes named_connection_nodes_;
   // The list of names we have seen in the file block.
   File_block_names file_block_names_;
   // Mapping from import file names to packages.
@@ -1215,11 +1145,8 @@  class Function
   // Import a function.
   static void
   import_func(Import*, std::string* pname, Typed_identifier** receiver,
-	      Node::Escapement_lattice* rcvr_escape,
 	      Typed_identifier_list** pparameters,
-	      Node::Escape_states** pparam_escapes,
-	      Typed_identifier_list** presults, bool* is_varargs,
-	      bool* has_escape_info);
+	      Typed_identifier_list** presults, bool* is_varargs);
 
  private:
   // Type for mapping from label names to Label objects.
Index: gcc/go/gofrontend/import.cc
===================================================================
--- gcc/go/gofrontend/import.cc	(revision 234304)
+++ gcc/go/gofrontend/import.cc	(working copy)
@@ -502,28 +502,16 @@  Import::import_func(Package* package)
 {
   std::string name;
   Typed_identifier* receiver;
-  Node::Escapement_lattice rcvr_escape;
   Typed_identifier_list* parameters;
-  Node::Escape_states* param_escapes;
   Typed_identifier_list* results;
   bool is_varargs;
-  bool has_escape_info;
-  Function::import_func(this, &name, &receiver, &rcvr_escape, &parameters,
-			&param_escapes, &results, &is_varargs,
-			&has_escape_info);
+  Function::import_func(this, &name, &receiver,
+			&parameters, &results, &is_varargs);
   Function_type *fntype = Type::make_function_type(receiver, parameters,
 						   results, this->location_);
   if (is_varargs)
     fntype->set_is_varargs();
 
-  if (has_escape_info)
-    {
-      if (fntype->is_method())
-	fntype->set_receiver_escape_state(rcvr_escape);
-      fntype->set_parameter_escape_states(param_escapes);
-      fntype->set_has_escape_info();
-    }
-
   Location loc = this->location_;
   Named_object* no;
   if (fntype->is_method())
@@ -774,19 +762,6 @@  Import::read_type()
   return type;
 }
 
-// Read escape info in the import stream.
-
-Node::Escapement_lattice
-Import::read_escape_info()
-{
-  Stream* stream = this->stream_;
-  this->require_c_string("<escape ");
-
-  int escape_value = stream->get_char() - '0';
-  this->require_c_string(">");
-  return Node::Escapement_lattice(escape_value);
-}
-
 // Register the builtin types.
 
 void
Index: gcc/go/gofrontend/import.h
===================================================================
--- gcc/go/gofrontend/import.h	(revision 234304)
+++ gcc/go/gofrontend/import.h	(working copy)
@@ -7,7 +7,6 @@ 
 #ifndef GO_IMPORT_H
 #define GO_IMPORT_H
 
-#include "escape.h"
 #include "export.h"
 #include "go-linemap.h"
 
@@ -198,10 +197,6 @@  class Import
   Type*
   read_type();
 
-  // Read escape information.
-  Node::Escapement_lattice
-  read_escape_info();
-
  private:
   static Stream*
   try_package_in_directory(const std::string&, Location);
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 235608)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -14,7 +14,6 @@ 
 #include "backend.h"
 #include "statements.h"
 #include "ast-dump.h"
-#include "dataflow.h"
 
 // Class Statement.
 
@@ -4821,22 +4820,6 @@  Select_clauses::Select_clause::check_typ
     error_at(this->location(), "invalid receive on send-only channel");
 }
 
-// Analyze the dataflow across each case statement.
-
-void
-Select_clauses::Select_clause::analyze_dataflow(Dataflow* dataflow)
-{
-  if (this->is_default_)
-    return;
-
-  // For a CommClause, the dataflow analysis should record a definition of
-  // VAR and CLOSEDVAR
-  if (this->var_ != NULL && !this->var_->is_sink())
-    dataflow->add_def(this->var_, this->channel_, NULL, false);
-  if (this->closedvar_ != NULL && !this->closedvar_->is_sink())
-    dataflow->add_def(this->closedvar_, this->channel_, NULL, false);
-}
-
 // Whether this clause may fall through to the statement which follows
 // the overall select statement.
 
@@ -4955,17 +4938,6 @@  Select_clauses::check_types()
     p->check_types();
 }
 
-// Analyze the dataflow across each case statement.
-
-void
-Select_clauses::analyze_dataflow(Dataflow* dataflow)
-{
-  for (Clauses::iterator p = this->clauses_.begin();
-       p != this->clauses_.end();
-       ++p)
-    p->analyze_dataflow(dataflow);
-}
-
 // Return whether these select clauses fall through to the statement
 // following the overall select statement.
 
Index: gcc/go/gofrontend/statements.h
===================================================================
--- gcc/go/gofrontend/statements.h	(revision 234304)
+++ gcc/go/gofrontend/statements.h	(working copy)
@@ -47,7 +47,6 @@  class Bexpression;
 class Bstatement;
 class Bvariable;
 class Ast_dump_context;
-class Dataflow;
 
 // This class is used to traverse assignments made by a statement
 // which makes assignments.
@@ -860,10 +859,6 @@  class Select_clauses
   void
   check_types();
 
-  // Analyze the dataflow across each case statement.
-  void
-  analyze_dataflow(Dataflow*);
-
   // Whether the select clauses may fall through to the statement
   // which follows the overall select statement.
   bool
@@ -920,10 +915,6 @@  class Select_clauses
     void
     check_types();
 
-    // Analyze the dataflow across each case statement.
-    void
-    analyze_dataflow(Dataflow*);
-
     // Return true if this is the default clause.
     bool
     is_default() const
@@ -1030,10 +1021,6 @@  class Select_statement : public Statemen
   Unnamed_label*
   break_label();
 
-  void
-  analyze_dataflow(Dataflow* dataflow)
-  { this->clauses_->analyze_dataflow(dataflow); }
-
  protected:
   int
   do_traverse(Traverse* traverse)
Index: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 234304)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -8,7 +8,6 @@ 
 #define GO_TYPES_H
 
 #include "go-linemap.h"
-#include "escape.h"
 
 class Gogo;
 class Package;
@@ -1779,7 +1778,7 @@  class Function_type : public Type
     : Type(TYPE_FUNCTION),
       receiver_(receiver), parameters_(parameters), results_(results),
       location_(location), is_varargs_(false), is_builtin_(false),
-      has_escape_info_(false), fnbtype_(NULL), parameter_escape_states_(NULL)
+      fnbtype_(NULL)
   { }
 
   // Get the receiver.
@@ -1787,16 +1786,6 @@  class Function_type : public Type
   receiver() const
   { return this->receiver_; }
 
-  // Get the escape state of the receiver.
-  const Node::Escapement_lattice&
-  receiver_escape_state() const
-  { return this->receiver_escape_state_; }
-
-  // Set the escape state of the receiver.
-  void
-  set_receiver_escape_state(const Node::Escapement_lattice& e)
-  { this->receiver_escape_state_ = e; }
-
   // Get the return names and types.
   const Typed_identifier_list*
   results() const
@@ -1807,16 +1796,6 @@  class Function_type : public Type
   parameters() const
   { return this->parameters_; }
 
-  // Get the escape states associated with each parameter.
-  const Node::Escape_states*
-  parameter_escape_states() const
-  { return this->parameter_escape_states_; }
-
-  // Set the escape states of the parameters.
-  void
-  set_parameter_escape_states(Node::Escape_states* states)
-  { this->parameter_escape_states_ = states; }
-
   // Whether this is a varargs function.
   bool
   is_varargs() const
@@ -1827,11 +1806,6 @@  class Function_type : public Type
   is_builtin() const
   { return this->is_builtin_; }
 
-  // Whether this contains escape information.
-  bool
-  has_escape_info() const
-  { return this->has_escape_info_; }
-
   // The location where this type was defined.
   Location
   location() const
@@ -1862,11 +1836,6 @@  class Function_type : public Type
   set_is_builtin()
   { this->is_builtin_ = true; }
 
-  // Record that this has escape information.
-  void
-  set_has_escape_info()
-  { this->has_escape_info_ = true; }
-
   // Import a function type.
   static Function_type*
   do_import(Import*);
@@ -1978,16 +1947,9 @@  class Function_type : public Type
   // Whether this is a special builtin function which can not simply
   // be called.  This is used for len, cap, etc.
   bool is_builtin_;
-  // Whether escape information for the receiver and parameters has been
-  // recorded.
-  bool has_escape_info_;
   // The backend representation of this type for backend function
   // declarations and definitions.
   Btype* fnbtype_;
-  // The escape state of the receiver.
-  Node::Escapement_lattice receiver_escape_state_;
-  // The escape states of each parameter.
-  Node::Escape_states* parameter_escape_states_;
 };
 
 // The type of a function's backend representation.