// escape.cc -- Go escape analysis (based on Go compiler algorithm).

// Copyright 2016 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 <limits>
#include <stack>
#include <sstream>

#include "gogo.h"
#include "types.h"
#include "expressions.h"
#include "statements.h"
#include "escape.h"
#include "lex.h"
#include "ast-dump.h"
#include "go-optimize.h"
#include "go-diagnostics.h"
#include "go-sha1.h"

// class Node.

// Return the node's type, if it makes sense for it to have one.

Type*
Node::type() const
{
  if (this->object() != NULL
      && this->object()->is_variable())
    return this->object()->var_value()->type();
  else if (this->object() != NULL
	   && this->object()->is_function())
    return this->object()->func_value()->type();
  else if (this->expr() != NULL)
    return this->expr()->type();
  else if (this->is_indirect())
    {
      if (this->child()->type()->deref()->is_void_type())
        // This is a void*. The referred type can be actually any type,
        // which may also be pointer. We model it as another void*, so
        // we don't lose pointer-ness.
        return this->child()->type();
      else if (this->child()->type()->is_slice_type())
        // We model "indirect" of a slice as dereferencing its pointer
        // field (to get element). Use element type here.
        return this->child()->type()->array_type()->element_type();
      else if (this->child()->type()->is_string_type())
        return Type::lookup_integer_type("uint8");
      else
        return this->child()->type()->deref();
    }
  else if (this->statement() != NULL
           && this->statement()->temporary_statement() != NULL)
    return this->statement()->temporary_statement()->type();
  else
    return NULL;
}

// A helper for reporting; return this node's location.

Location
Node::location() const
{
  if (this->object() != NULL && !this->object()->is_sink())
    return this->object()->location();
  else if (this->expr() != NULL)
    return this->expr()->location();
  else if (this->statement() != NULL)
    return this->statement()->location();
  else if (this->is_indirect())
    return this->child()->location();
  else
    return Linemap::unknown_location();
}

// A helper for reporting; return the location where the underlying
// object is defined.

Location
Node::definition_location() const
{
  if (this->object() != NULL && !this->object()->is_sink())
    {
      Named_object* no = this->object();
      if (no->is_variable() || no->is_result_variable())
        return no->location();
    }
  else if (this->expr() != NULL)
    {
      Var_expression* ve = this->expr()->var_expression();
      if (ve != NULL)
        {
          Named_object* no = ve->named_object();
          if (no->is_variable() || no->is_result_variable())
            return no->location();
        }
      Enclosed_var_expression* eve = this->expr()->enclosed_var_expression();
      if (eve != NULL)
        {
          Named_object* no = eve->variable();
          if (no->is_variable() || no->is_result_variable())
            return no->location();
        }
    }
  return this->location();
}

// To match the cmd/gc debug output, strip away the packed prefixes on functions
// and variable/expressions.

std::string
strip_packed_prefix(Gogo* gogo, const std::string& s)
{
  std::string packed_prefix = "." + gogo->pkgpath() + ".";
  std::string fmt = s;
  for (size_t pos = fmt.find(packed_prefix);
       pos != std::string::npos;
       pos = fmt.find(packed_prefix))
    fmt.erase(pos, packed_prefix.length());
  return fmt;
}

// A helper for debugging; return this node's AST formatted string.
// This is an implementation of gc's Nconv with obj.FmtShort.

std::string
Node::ast_format(Gogo* gogo) const
{
  std::ostringstream ss;
  if (this->is_sink())
    ss << ".sink";
  else if (this->object() != NULL)
    {
      Named_object* no = this->object();
      if (no->is_function() && no->func_value()->enclosing() != NULL)
	return "func literal";
      ss << no->message_name();
    }
  else if (this->expr() != NULL)
    {
      Expression* e = this->expr();
      bool is_call = e->call_expression() != NULL;
      if (is_call)
	e->call_expression()->fn();
      Func_expression* fe = e->func_expression();;

      bool is_closure = fe != NULL && fe->closure() != NULL;
      if (is_closure)
	{
	  if (is_call)
	    return "(func literal)()";
	  return "func literal";
	}
      Ast_dump_context::dump_to_stream(this->expr(), &ss);
    }
  else if (this->statement() != NULL)
    {
      Statement* s = this->statement();
      Goto_unnamed_statement* unnamed = s->goto_unnamed_statement();
      if (unnamed != NULL)
	{
	  Statement* derived = unnamed->unnamed_label()->derived_from();
	  if (derived != NULL)
	    {
	      switch (derived->classification())
		{
		case Statement::STATEMENT_FOR:
		case Statement::STATEMENT_FOR_RANGE:
		  return "for loop";
		  break;

		case Statement::STATEMENT_SWITCH:
		  return "switch";
		  break;

		case Statement::STATEMENT_TYPE_SWITCH:
		  return "type switch";
		  break;

		default:
		  break;
		}
	    }
	}
      Temporary_statement* tmp = s->temporary_statement();
      if (tmp != NULL)
        {
          // Temporary's format can never match gc's output, and
          // temporaries are inserted differently anyway. We just
          // print something convenient.
          ss << "tmp." << (uintptr_t) tmp;
          if (tmp->init() != NULL)
            {
              ss << " [ = ";
              Ast_dump_context::dump_to_stream(tmp->init(), &ss);
              ss << " ]";
            }
        }
      else
        Ast_dump_context::dump_to_stream(s, &ss);
    }
  else if (this->is_indirect())
    return "*(" + this->child()->ast_format(gogo) + ")";

  std::string s = strip_packed_prefix(gogo, ss.str());

  // trim trailing space
  return s.substr(0, s.find_last_not_of(' ') + 1);
}

// A helper for debugging; return this node's detailed format string.
// This is an implementation of gc's Jconv with obj.FmtShort.

std::string
Node::details()
{
  std::stringstream details;

  if (!this->is_sink())
    details << " l(" << Linemap::location_to_line(this->location()) << ")";

  bool is_varargs = false;
  bool is_address_taken = false;
  bool is_in_heap = false;
  bool is_assigned = false;
  std::string class_name;

  Expression* e = this->expr();
  Named_object* node_object = NULL;
  if (this->object() != NULL)
    node_object = this->object();
  else if (e != NULL && e->var_expression() != NULL)
    node_object = e->var_expression()->named_object();

  if (node_object)
    {
      // TODO(cmang): For named variables and functions, we want to output
      // the function depth.
      if (node_object->is_variable())
	{
	  Variable* var = node_object->var_value();
	  is_varargs = var->is_varargs_parameter();
	  is_address_taken = (var->is_address_taken()
			      || var->is_non_escaping_address_taken());
	  is_in_heap = var->is_in_heap();
	  is_assigned = var->init() != NULL;

	  if (var->is_global())
	    class_name = "PEXTERN";
	  else if (var->is_parameter())
	    class_name = "PPARAM";
	  else if (var->is_closure())
	    class_name = "PPARAMREF";
	  else
	    class_name = "PAUTO";
	}
      else if (node_object->is_result_variable())
	class_name = "PPARAMOUT";
      else if (node_object->is_function()
	       || node_object->is_function_declaration())
	class_name = "PFUNC";
    }
  else if (e != NULL && e->enclosed_var_expression() != NULL)
    {
      Named_object* enclosed = e->enclosed_var_expression()->variable();
      if (enclosed->is_variable())
	{
	  Variable* var = enclosed->var_value();
	  is_address_taken = (var->is_address_taken()
			      || var->is_non_escaping_address_taken());
	}
      else
	{
	  Result_variable* var = enclosed->result_var_value();
	  is_address_taken = (var->is_address_taken()
			      || var->is_non_escaping_address_taken());
	}
      class_name = "PPARAMREF";
    }

  if (!class_name.empty())
    {
      details << " class(" << class_name;
      if (is_in_heap)
	details << ",heap";
      details << ")";
    }

  switch ((this->encoding() & ESCAPE_MASK))
    {
    case Node::ESCAPE_UNKNOWN:
      break;

    case Node::ESCAPE_HEAP:
      details << " esc(h)";
      break;

    case Node::ESCAPE_NONE:
      details << " esc(no)";
      break;

    case Node::ESCAPE_NEVER:
      details << " esc(N)";
      break;

    default:
      details << " esc(" << this->encoding() << ")";
      break;
    }

  if (this->state_ != NULL && this->state_->loop_depth != 0)
    details << " ld(" << this->state_->loop_depth << ")";

  if (is_varargs)
    details << " isddd(1)";
  if (is_address_taken)
    details << " addrtaken";
  if (is_assigned)
    details << " assigned";

  return details.str();
}

std::string
Node::op_format() const
{
  std::stringstream op;
  Ast_dump_context adc(&op, false);
  if (this->expr() != NULL)
    {
      Expression* e = this->expr();
      switch (e->classification())
	{
	case Expression::EXPRESSION_UNARY:
	  adc.dump_operator(e->unary_expression()->op());
	  break;

	case Expression::EXPRESSION_BINARY:
	  adc.dump_operator(e->binary_expression()->op());
	  break;

	case Expression::EXPRESSION_CALL:
	  op << "function call";
	  break;

	case Expression::EXPRESSION_FUNC_REFERENCE:
	  if (e->func_expression()->is_runtime_function())
	    {
	      switch (e->func_expression()->runtime_code())
		{
		case Runtime::GOPANIC:
		  op << "panic";
		  break;

		case Runtime::GROWSLICE:
		  op << "append";
		  break;

		case Runtime::SLICECOPY:
		case Runtime::SLICESTRINGCOPY:
		case Runtime::TYPEDSLICECOPY:
		  op << "copy";
		  break;

		case Runtime::MAKECHAN:
		case Runtime::MAKECHAN64:
		case Runtime::MAKEMAP:
		case Runtime::MAKESLICE:
		case Runtime::MAKESLICE64:
		  op << "make";
		  break;

		case Runtime::DEFERPROC:
		  op << "defer";
		  break;

		case Runtime::GORECOVER:
		  op << "recover";
		  break;

		case Runtime::CLOSE:
		  op << "close";
		  break;

		default:
		  break;
		}
	    }
	  break;

	case Expression::EXPRESSION_ALLOCATION:
	  op << "new";
	  break;

	case Expression::EXPRESSION_RECEIVE:
	  op << "<-";
	  break;

	default:
	  break;
	}
    }

  if (this->statement() != NULL)
    {
      switch (this->statement()->classification())
	{
	case Statement::STATEMENT_DEFER:
	  op << "defer";
	  break;

	case Statement::STATEMENT_RETURN:
	  op << "return";
	  break;

	default:
	  break;
	}
    }
  if (this->is_indirect())
    op << "*";
  return op.str();
}

// Return this node's state, creating it if has not been initialized.

Node::Escape_state*
Node::state(Escape_context* context, Named_object* fn)
{
  if (this->state_ == NULL)
    {
      if (this->expr() != NULL && this->expr()->var_expression() != NULL)
	{
	  // Tie state of variable references to underlying variables.
	  Named_object* var_no = this->expr()->var_expression()->named_object();
	  Node* var_node = Node::make_node(var_no);
	  this->state_ = var_node->state(context, fn);
	}
      else
	{
	  this->state_ = new Node::Escape_state;
	  if (fn == NULL)
	    fn = context->current_function();

	  this->state_->fn = fn;
	}
    }
  go_assert(this->state_ != NULL);
  return this->state_;
}

Node::~Node()
{
  if (this->state_ != NULL)
    {
      if (this->expr() == NULL || this->expr()->var_expression() == NULL)
        // Var expression Node is excluded since it shares state with the
        // underlying var Node.
        delete this->state_;
    }
}

int
Node::encoding()
{
  if (this->expr() != NULL
      && this->expr()->var_expression() != NULL)
    {
      // Get the underlying object's encoding.
      Named_object* no = this->expr()->var_expression()->named_object();
      int enc = Node::make_node(no)->encoding();
      this->encoding_ = enc;
    }
  return this->encoding_;
}

void
Node::set_encoding(int enc)
{
  this->encoding_ = enc;
  if (this->expr() != NULL)
    {
      if (this->expr()->var_expression() != NULL)
        {
          // Set underlying object as well.
          Named_object* no = this->expr()->var_expression()->named_object();
          Node::make_node(no)->set_encoding(enc);
        }
      else if (this->expr()->func_expression() != NULL)
        {
          // Propagate the escape state to the underlying
          // closure (heap expression).
          Expression* closure = this->expr()->func_expression()->closure();
          if (closure != NULL)
            Node::make_node(closure)->set_encoding(enc);
        }
    }
}

bool
Node::is_big(Escape_context* context) const
{
  Type* t = this->type();
  if (t == NULL
      || t->is_call_multiple_result_type()
      || t->is_sink_type()
      || t->is_void_type()
      || t->is_abstract())
    return false;

  int64_t size;
  bool ok = t->backend_type_size(context->gogo(), &size);
  bool big = ok && (size < 0 || size > 10 * 1024 * 1024);

  if (this->expr() != NULL)
    {
      if (this->expr()->allocation_expression() != NULL)
	{
	  ok = t->deref()->backend_type_size(context->gogo(), &size);
	  big = big || size <= 0 || size >= (1 << 16);
	}
      else if (this->expr()->call_expression() != NULL)
	{
	  Call_expression* call = this->expr()->call_expression();
	  Func_expression* fn = call->fn()->func_expression();
	  if (fn != NULL
	      && fn->is_runtime_function()
	      && (fn->runtime_code() == Runtime::MAKESLICE
		  || fn->runtime_code() == Runtime::MAKESLICE64))
	    {
	      // Second argument is length.
	      Expression_list::iterator p = call->args()->begin();
	      ++p;

              Expression* e = *p;
              if (e->temporary_reference_expression() != NULL)
                {
                  Temporary_reference_expression* tre = e->temporary_reference_expression();
                  if (tre->statement() != NULL && tre->statement()->init() != NULL)
                    e = tre->statement()->init();
                }

	      Numeric_constant nc;
	      unsigned long v;
	      if (e->numeric_constant_value(&nc)
		  && nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_VALID)
		big = big || v >= (1 << 16);
	    }
	}
    }

  return big;
}

bool
Node::is_sink() const
{
  if (this->object() != NULL
      && this->object()->is_sink())
    return true;
  else if (this->expr() != NULL
	   && this->expr()->is_sink_expression())
    return true;
  return false;
}

std::map<Named_object*, Node*> Node::objects;
std::map<Expression*, Node*> Node::expressions;
std::map<Statement*, Node*> Node::statements;
std::vector<Node*> Node::indirects;

// Make a object node or return a cached node for this object.

Node*
Node::make_node(Named_object* no)
{
  if (Node::objects.find(no) != Node::objects.end())
    return Node::objects[no];

  Node* n = new Node(no);
  std::pair<Named_object*, Node*> val(no, n);
  Node::objects.insert(val);
  return n;
}

// Make an expression node or return a cached node for this expression.

Node*
Node::make_node(Expression* e)
{
  if (Node::expressions.find(e) != Node::expressions.end())
    return Node::expressions[e];

  Node* n = new Node(e);
  std::pair<Expression*, Node*> val(e, n);
  Node::expressions.insert(val);
  return n;
}

// Make a statement node or return a cached node for this statement.

Node*
Node::make_node(Statement* s)
{
  if (Node::statements.find(s) != Node::statements.end())
    return Node::statements[s];

  Node* n = new Node(s);
  std::pair<Statement*, Node*> val(s, n);
  Node::statements.insert(val);
  return n;
}

// Make an indirect node with given child.

Node*
Node::make_indirect_node(Node* child)
{
  Node* n = new Node(child);
  Node::indirects.push_back(n);
  return n;
}

// Returns the maximum of an exisiting escape value
// (and its additional parameter flow flags) and a new escape type.

int
Node::max_encoding(int e, int etype)
{
  if ((e & ESCAPE_MASK) > etype)
    return e;
  if (etype == Node::ESCAPE_NONE || etype == Node::ESCAPE_RETURN)
    return (e & ~ESCAPE_MASK) | etype;
  return etype;
}

// Return a modified encoding for an input parameter that flows into an
// output parameter.

int
Node::note_inout_flows(int e, int index, Level level)
{
  // Flow+level is encoded in two bits.
  // 00 = not flow, xx = level+1 for 0 <= level <= maxEncodedLevel.
  // 16 bits for Esc allows 6x2bits or 4x3bits or 3x4bits if additional
  // information would be useful.
  if (level.value() <= 0 && level.suffix_value() > 0)
    return Node::max_encoding(e|ESCAPE_CONTENT_ESCAPES, Node::ESCAPE_NONE);
  if (level.value() < 0)
    return Node::ESCAPE_HEAP;
  if (level.value() >  ESCAPE_MAX_ENCODED_LEVEL)
    level = Level::From(ESCAPE_MAX_ENCODED_LEVEL);

  int encoded = level.value() + 1;
  int shift = ESCAPE_BITS_PER_OUTPUT_IN_TAG * index + ESCAPE_RETURN_BITS;
  int old = (e >> shift) & ESCAPE_BITS_MASK_FOR_TAG;
  if (old == 0
      || (encoded != 0 && encoded < old))
    old = encoded;

  int encoded_flow = old << shift;
  if (((encoded_flow >> shift) & ESCAPE_BITS_MASK_FOR_TAG) != old)
    {
      // Failed to encode.  Put this on the heap.
      return Node::ESCAPE_HEAP;
    }

  return (e & ~(ESCAPE_BITS_MASK_FOR_TAG << shift)) | encoded_flow;
}

// Class Escape_context.

Escape_context::Escape_context(Gogo* gogo, bool recursive)
  : gogo_(gogo), current_function_(NULL), recursive_(recursive),
    sink_(Node::make_node(Named_object::make_sink())), loop_depth_(0),
    flood_id_(0), pdepth_(0)
{
  // The sink always escapes to heap and strictly lives outside of the
  // current function i.e. loop_depth == -1.
  Node::Escape_state* state = this->sink_->state(this, NULL);
  state->loop_depth = -1;
}

std::string
debug_function_name(Named_object* fn)
{
  if (fn == NULL)
    return "<S>";

  if (!fn->is_function())
    return Gogo::unpack_hidden_name(fn->name());

  std::string fnname = Gogo::unpack_hidden_name(fn->name());
  if (fn->func_value()->is_method())
    {
      // Methods in gc compiler are named "T.m" or "(*T).m" where
      // T is the receiver type. Add the receiver here.
      Type* rt = fn->func_value()->type()->receiver()->type();
      switch (rt->classification())
	{
	case Type::TYPE_NAMED:
	  fnname = rt->named_type()->name() + "." + fnname;
	  break;

	case Type::TYPE_POINTER:
	  {
	    Named_type* nt = rt->points_to()->named_type();
	    if (nt != NULL)
	      fnname = "(*" + nt->name() + ")." + fnname;
	    break;
	  }

	default:
	  break;
	}
    }

  return fnname;
}

// Return the name of the current function.

std::string
Escape_context::current_function_name() const
{
  return debug_function_name(this->current_function_);
}

// Initialize the dummy return values for this Node N using the results
// in FNTYPE.

void
Escape_context::init_retvals(Node* n, Function_type* fntype)
{
  if (fntype == NULL || fntype->results() == NULL)
    return;

  Node::Escape_state* state = n->state(this, NULL);
  state->retvals.clear();
  Location loc = n->location();

  int i = 0;
  char buf[50];
  for (Typed_identifier_list::const_iterator p = fntype->results()->begin();
       p != fntype->results()->end();
       ++p, ++i)
    {
      snprintf(buf, sizeof buf, ".out%d", i);
      Variable* dummy_var = new Variable(p->type(), NULL, false, false,
					 false, loc);
      dummy_var->set_is_used();
      Named_object* dummy_no =
	Named_object::make_variable(buf, NULL, dummy_var);
      Node* dummy_node = Node::make_node(dummy_no);
      // Initialize the state of the dummy output node.
      Node::Escape_state* dummy_node_state = dummy_node->state(this, NULL);
      dummy_node_state->loop_depth = this->loop_depth_;

      // Add dummy node to the retvals of n.
      state->retvals.push_back(dummy_node);
    }
}


// Apply an indirection to N and return the result.

Node*
Escape_context::add_dereference(Node* n)
{
  Expression* e = n->expr();
  Location loc = n->location();
  Node* ind;
  if (e != NULL
      && e->type()->points_to() != NULL
      && !e->type()->points_to()->is_void_type())
    {
      // We don't dereference void*, which can be actually any pointer type.
      Expression* deref_expr = Expression::make_unary(OPERATOR_MULT, e, loc);
      ind = Node::make_node(deref_expr);
    }
  else
    // The gc compiler simply makes an OIND node. We can't do it
    // for non-pointer type because that will result in a type error.
    // Instead, we model this by making a node with a special flavor.
    ind = Node::make_indirect_node(n);

  // Initialize the state.
  Node::Escape_state* state = ind->state(this, NULL);
  state->loop_depth = n->state(this, NULL)->loop_depth;
  return ind;
}

void
Escape_context::track(Node* n)
{
  n->set_encoding(Node::ESCAPE_NONE);
  // Initialize this node's state if it hasn't been encountered
  // before.
  Node::Escape_state* state = n->state(this, NULL);
  state->loop_depth = this->loop_depth_;

  this->noesc_.push_back(n);
}

// Return the string representation of an escapement encoding.

std::string
Escape_note::make_tag(int encoding)
{
  char buf[50];
  snprintf(buf, sizeof buf, "esc:0x%x", encoding);
  return buf;
}

// Return the escapement encoding for a string tag.

int
Escape_note::parse_tag(std::string* tag)
{
  if (tag == NULL || tag->substr(0, 4) != "esc:")
    return Node::ESCAPE_UNKNOWN;
  int encoding = (int)strtol(tag->substr(4).c_str(), NULL, 0);
  if (encoding == 0)
    return Node::ESCAPE_UNKNOWN;
  return encoding;
}


// The -fgo-optimize-alloc flag activates this escape analysis.

Go_optimize optimize_allocation_flag("allocs", true);

// A helper function to compute whether a function name has a
// matching hash value.

static bool
escape_hash_match(std::string suffix, std::string name)
{
  if (suffix.empty())
    return true;
  if (suffix.at(0) == '-')
    return !escape_hash_match(suffix.substr(1), name);

  const char* p = name.c_str();
  Go_sha1_helper* sha1_helper = go_create_sha1_helper();
  sha1_helper->process_bytes(p, strlen(p));
  std::string s = sha1_helper->finish();
  delete sha1_helper;

  int j = suffix.size() - 1;
  for (int i = s.size() - 1; i >= 0; i--)
    {
      char c = s.at(i);
      for (int k = 0; k < 8; k++, j--, c>>=1)
        {
          if (j < 0)
            return true;
          char bit = suffix.at(j) - '0';
          if ((c&1) != bit)
            return false;
        }
    }
  return false;
}

// Analyze the program flow for escape information.

void
Gogo::analyze_escape()
{
  if (saw_errors())
    return;

  if (!optimize_allocation_flag.is_enabled()
      && !this->compiling_runtime())
    // We always run escape analysis when compiling runtime.
    return;

  // Discover strongly connected groups of functions to analyze for escape
  // information in this package.
  this->discover_analysis_sets();

  if (!this->debug_escape_hash().empty())
    std::cerr << "debug-escape-hash " << this->debug_escape_hash() << "\n";

  for (std::vector<Analysis_set>::iterator p = this->analysis_sets_.begin();
       p != this->analysis_sets_.end();
       ++p)
    {
      std::vector<Named_object*> stack = p->first;

      if (!this->debug_escape_hash().empty())
        {
          bool match = false;
          for (std::vector<Named_object*>::const_iterator fn = stack.begin();
               fn != stack.end();
               ++fn)
            match = match || escape_hash_match(this->debug_escape_hash(), (*fn)->message_name());
          if (!match)
            {
              // Escape analysis won't run on these functions, but still
              // need to tag them, so the caller knows.
              for (std::vector<Named_object*>::iterator fn = stack.begin();
                   fn != stack.end();
                   ++fn)
                if ((*fn)->is_function())
                  {
                    Function_type* fntype = (*fn)->func_value()->type();
                    fntype->set_is_tagged();

                    std::cerr << "debug-escape-hash disables " << debug_function_name(*fn) << "\n";
                  }

              continue;
            }
          for (std::vector<Named_object*>::const_iterator fn = stack.begin();
               fn != stack.end();
               ++fn)
            if ((*fn)->is_function())
              std::cerr << "debug-escape-hash triggers " << debug_function_name(*fn) << "\n";
        }

      Escape_context* context = new Escape_context(this, p->second);

      // Analyze the flow of each function; build the connection graph.
      // This is the assign phase.
      for (std::vector<Named_object*>::reverse_iterator fn = stack.rbegin();
           fn != stack.rend();
           ++fn)
	{
	  context->set_current_function(*fn);
	  this->assign_connectivity(context, *fn);
	}

      // Propagate levels across each dst.  This is the flood phase.
      std::set<Node*> dsts = context->dsts();
      Unordered_map(Node*, int) escapes;
      for (std::set<Node*>::iterator n = dsts.begin();
           n != dsts.end();
           ++n)
        {
          escapes[*n] = (*n)->encoding();
          this->propagate_escape(context, *n);
        }
      for (;;)
        {
          // Reflood if the roots' escape states increase. Run until fix point.
          // This is rare.
          bool done = true;
          for (std::set<Node*>::iterator n = dsts.begin();
               n != dsts.end();
               ++n)
            {
              if ((*n)->object() == NULL
                  && ((*n)->expr() == NULL
                      || ((*n)->expr()->var_expression() == NULL
                          && (*n)->expr()->enclosed_var_expression() == NULL
                          && (*n)->expr()->func_expression() == NULL)))
                continue;
              if (escapes[*n] != (*n)->encoding())
                {
                  done = false;
                  if (this->debug_escape_level() > 2)
                    go_inform((*n)->location(), "Reflooding %s %s",
                              debug_function_name((*n)->state(context, NULL)->fn).c_str(),
                              (*n)->ast_format(this).c_str());
                  escapes[*n] = (*n)->encoding();
                  this->propagate_escape(context, *n);
                }
            }
          if (done)
            break;
        }

      // Tag each exported function's parameters with escape information.
      for (std::vector<Named_object*>::iterator fn = stack.begin();
           fn != stack.end();
           ++fn)
        this->tag_function(context, *fn);

      if (this->debug_escape_level() != 0)
	{
	  std::vector<Node*> noesc = context->non_escaping_nodes();
	  for (std::vector<Node*>::const_iterator n = noesc.begin();
	       n != noesc.end();
	       ++n)
	    {
	      Node::Escape_state* state = (*n)->state(context, NULL);
	      if ((*n)->encoding() == Node::ESCAPE_NONE)
		go_inform((*n)->location(), "%s %s does not escape",
			  strip_packed_prefix(this, debug_function_name(state->fn)).c_str(),
			  (*n)->ast_format(this).c_str());
	    }
	}
      delete context;
    }
}

// Traverse the program, discovering the functions that are roots of strongly
// connected components.  The goal of this phase to produce a set of functions
// that must be analyzed in order.

class Escape_analysis_discover : public Traverse
{
 public:
  Escape_analysis_discover(Gogo* gogo)
    : Traverse(traverse_functions | traverse_func_declarations),
      gogo_(gogo), component_ids_()
  { }

  int
  function(Named_object*);

  int
  function_declaration(Named_object*);

  int
  visit(Named_object*);

  int
  visit_code(Named_object*, int);

 private:
  // A counter used to generate the ID for the function node in the graph.
  static int id;

  // Type used to map functions to an ID in a graph of connected components.
  typedef Unordered_map(Named_object*, int) Component_ids;

  // The Go IR.
  Gogo* gogo_;
  // The list of functions encountered during connected component discovery.
  Component_ids component_ids_;
  // The stack of functions that this component consists of.
  std::stack<Named_object*> stack_;
};

int Escape_analysis_discover::id = 0;

// Visit each function.

int
Escape_analysis_discover::function(Named_object* fn)
{
  this->visit(fn);
  return TRAVERSE_CONTINUE;
}

int
Escape_analysis_discover::function_declaration(Named_object* fn)
{
  this->visit(fn);
  return TRAVERSE_CONTINUE;
}

// Visit a function FN, adding it to the current stack of functions
// in this connected component.  If this is the root of the component,
// create a set of functions to be analyzed later.
//
// Finding these sets is finding strongly connected components
// in the static call graph.  The algorithm for doing that is taken
// from Sedgewick, Algorithms, Second Edition, p. 482, with two
// adaptations.
//
// First, a closure (fn->func_value()->enclosing() == NULL) cannot be the
// root of a connected component.  Refusing to use it as a root
// forces it into the component of the function in which it appears.
// This is more convenient for escape analysis.
//
// Second, each function becomes two virtual nodes in the graph,
// with numbers n and n+1. We record the function's node number as n
// but search from node n+1. If the search tells us that the component
// number (min) is n+1, we know that this is a trivial component: one function
// plus its closures. If the search tells us that the component number is
// n, then there was a path from node n+1 back to node n, meaning that
// the function set is mutually recursive. The escape analysis can be
// more precise when analyzing a single non-recursive function than
// when analyzing a set of mutually recursive functions.

int
Escape_analysis_discover::visit(Named_object* fn)
{
  Component_ids::const_iterator p = this->component_ids_.find(fn);
  if (p != this->component_ids_.end())
    // Already visited.
    return p->second;

  this->id++;
  int id = this->id;
  this->component_ids_[fn] = id;
  this->id++;
  int min = this->id;

  this->stack_.push(fn);
  min = this->visit_code(fn, min);
  if ((min == id || min == id + 1)
      && ((fn->is_function() && fn->func_value()->enclosing() == NULL)
          || fn->is_function_declaration()))
    {
      bool recursive = min == id;
      std::vector<Named_object*> group;

      for (; !this->stack_.empty(); this->stack_.pop())
	{
	  Named_object* n = this->stack_.top();
	  if (n == fn)
	    {
	      this->stack_.pop();
	      break;
	    }

	  group.push_back(n);
	  this->component_ids_[n] = std::numeric_limits<int>::max();
	}
      group.push_back(fn);
      this->component_ids_[fn] = std::numeric_limits<int>::max();

      std::reverse(group.begin(), group.end());
      this->gogo_->add_analysis_set(group, recursive);
    }

  return min;
}

// Helper class for discovery step.  Traverse expressions looking for
// function calls and closures to visit during the discovery step.

class Escape_discover_expr : public Traverse
{
 public:
  Escape_discover_expr(Escape_analysis_discover* ead, int min)
    : Traverse(traverse_expressions),
      ead_(ead), min_(min)
  { }

  int
  min()
  { return this->min_; }

  int
  expression(Expression** pexpr);

 private:
  // The original discovery analysis.
  Escape_analysis_discover* ead_;
  // The minimum component ID in this group.
  int min_;
};

// Visit any calls or closures found when discovering expressions.

int
Escape_discover_expr::expression(Expression** pexpr)
{
  Expression* e = *pexpr;
  Named_object* fn = NULL;
  if (e->call_expression() != NULL
      && e->call_expression()->fn()->func_expression() != NULL)
    {
      // Method call or function call.
      fn = e->call_expression()->fn()->func_expression()->named_object();
    }
  else if (e->func_expression() != NULL
           && e->func_expression()->closure() != NULL)
    {
      // Closure.
      fn = e->func_expression()->named_object();
    }

  if (fn != NULL)
    this->min_ = std::min(this->min_, this->ead_->visit(fn));
  return TRAVERSE_CONTINUE;
}

// Visit the body of each function, returns ID of the minimum connected
// component found in the body.

int
Escape_analysis_discover::visit_code(Named_object* fn, int min)
{
  if (!fn->is_function())
    return min;

  Escape_discover_expr ede(this, min);
  fn->func_value()->traverse(&ede);
  return ede.min();
}

// Discover strongly connected groups of functions to analyze.

void
Gogo::discover_analysis_sets()
{
  Escape_analysis_discover ead(this);
  this->traverse(&ead);
}

// Traverse all label and goto statements and mark the underlying label
// as looping or not looping.

class Escape_analysis_loop : public Traverse
{
 public:
  Escape_analysis_loop()
    : Traverse(traverse_statements)
  { }

  int
  statement(Block*, size_t*, Statement*);
};

int
Escape_analysis_loop::statement(Block*, size_t*, Statement* s)
{
  if (s->label_statement() != NULL)
    s->label_statement()->label()->set_nonlooping();
  else if (s->goto_statement() != NULL)
    {
      if (s->goto_statement()->label()->nonlooping())
        s->goto_statement()->label()->set_looping();
    }
  return TRAVERSE_CONTINUE;
}

// Traversal class used to look at all interesting statements within a function
// in order to build a connectivity graph between all nodes within a context's
// scope.

class Escape_analysis_assign : public Traverse
{
public:
  Escape_analysis_assign(Escape_context* context, Named_object* fn)
    : Traverse(traverse_statements
	       | traverse_expressions),
      context_(context), fn_(fn)
  { }

  // Model statements within a function as assignments and flows between nodes.
  int
  statement(Block*, size_t*, Statement*);

  // Model expressions within a function as assignments and flows between nodes.
  int
  expression(Expression**);

  // Model calls within a function as assignments and flows between arguments
  // and results.
  void
  call(Call_expression* call);

  // Model the assignment of DST to SRC.
  void
  assign(Node* dst, Node* src);

  // Model the assignment of DST to dereference of SRC.
  void
  assign_deref(Node* dst, Node* src);

  // Model the input-to-output assignment flow of one of a function call's
  // arguments, where the flow is encoding in NOTE.
  int
  assign_from_note(std::string* note, const std::vector<Node*>& dsts,
		   Node* src);

  // Record the flow of SRC to DST in DST.
  void
  flows(Node* dst, Node* src);

private:
  // The escape context for this set of functions.
  Escape_context* context_;
  // The current function being analyzed.
  Named_object* fn_;
};

// Helper function to detect self assignment like the following.
//
// func (b *Buffer) Foo() {
//   n, m := ...
//   b.buf = b.buf[n:m]
// }

static bool
is_self_assignment(Expression* lhs, Expression* rhs)
{
  Unary_expression* lue =
    (lhs->field_reference_expression() != NULL
     ? lhs->field_reference_expression()->expr()->unary_expression()
     : lhs->unary_expression());
  Var_expression* lve =
    (lue != NULL && lue->op() == OPERATOR_MULT ? lue->operand()->var_expression() : NULL);
  Array_index_expression* raie = rhs->array_index_expression();
  String_index_expression* rsie = rhs->string_index_expression();
  Expression* rarray =
    (raie != NULL && raie->end() != NULL && raie->array()->type()->is_slice_type()
     ? raie->array()
     : (rsie != NULL && rsie->type()->is_string_type() ? rsie->string() : NULL));
  Unary_expression* rue =
    (rarray != NULL && rarray->field_reference_expression() != NULL
     ? rarray->field_reference_expression()->expr()->unary_expression()
     : (rarray != NULL ? rarray->unary_expression() : NULL));
  Var_expression* rve =
    (rue != NULL && rue->op() == OPERATOR_MULT ? rue->operand()->var_expression() : NULL);
  return lve != NULL && rve != NULL
         && lve->named_object() == rve->named_object();
}

// Model statements within a function as assignments and flows between nodes.

int
Escape_analysis_assign::statement(Block*, size_t*, Statement* s)
{
  // Adjust the loop depth as we enter/exit blocks related to for statements.
  bool is_for_statement = (s->is_block_statement()
                           && s->block_statement()->is_lowered_for_statement());
  if (is_for_statement)
    this->context_->increase_loop_depth();

  s->traverse_contents(this);

  if (is_for_statement)
    this->context_->decrease_loop_depth();

  Gogo* gogo = this->context_->gogo();
  int debug_level = gogo->debug_escape_level();
  if (debug_level > 1
      && s->unnamed_label_statement() == NULL
      && s->expression_statement() == NULL
      && !s->is_block_statement())
    {
      Node* n = Node::make_node(s);
      std::string fn_name = this->context_->current_function_name();
      go_inform(s->location(), "[%d] %s esc: %s",
	        this->context_->loop_depth(), fn_name.c_str(),
	        n->ast_format(gogo).c_str());
    }

  switch (s->classification())
    {
    case Statement::STATEMENT_VARIABLE_DECLARATION:
      {
	Named_object* var = s->variable_declaration_statement()->var();
	Node* var_node = Node::make_node(var);
	Node::Escape_state* state = var_node->state(this->context_, NULL);
	state->loop_depth = this->context_->loop_depth();

	// Set the loop depth for this declaration.
	if (var->is_variable()
	    && var->var_value()->init() != NULL)
	  {
	    Node* init_node = Node::make_node(var->var_value()->init());
	    this->assign(var_node, init_node);
	  }
      }
      break;

    case Statement::STATEMENT_TEMPORARY:
      {
        Expression* init = s->temporary_statement()->init();
        if (init != NULL)
	  {
	    Node* n = Node::make_node(init);
	    if (s->temporary_statement()->value_escapes())
	      this->assign(this->context_->sink(), n);
	    else
	      this->assign(Node::make_node(s), n);
	  }
      }
      break;

    case Statement::STATEMENT_LABEL:
      {
	Label_statement* label_stmt = s->label_statement();
	if (label_stmt->label()->looping())
	  this->context_->increase_loop_depth();

	if (debug_level > 1)
	  {
	    std::string label_type = (label_stmt->label()->looping()
				      ? "looping"
				      : "nonlooping");
	    go_inform(s->location(), "%s %s label",
		      label_stmt->label()->name().c_str(),
		      label_type.c_str());
	  }
      }
      break;

    case Statement::STATEMENT_SWITCH:
    case Statement::STATEMENT_TYPE_SWITCH:
      // Want to model the assignment of each case variable to the switched upon
      // variable.  This should be lowered into assignment statements; nothing
      // to here if that's the case.
      break;

    case Statement::STATEMENT_ASSIGNMENT:
      {
	Assignment_statement* assn = s->assignment_statement();
        Expression* lhs = assn->lhs();
        Expression* rhs = assn->rhs();
        Node* lhs_node = Node::make_node(lhs);
        Node* rhs_node = Node::make_node(rhs);

        // Filter out the following special case.
        //
        // func (b *Buffer) Foo() {
        //   n, m := ...
        //   b.buf = b.buf[n:m]
        // }
        //
        // This assignment is a no-op for escape analysis,
        // it does not store any new pointers into b that were not already there.
        // However, without this special case b will escape.
        if (is_self_assignment(lhs, rhs))
          {
            if (debug_level != 0)
              go_inform(s->location(), "%s ignoring self-assignment to %s",
                        strip_packed_prefix(gogo, this->context_->current_function_name()).c_str(),
                        lhs_node->ast_format(gogo).c_str());
            break;
          }

        this->assign(lhs_node, rhs_node);
      }
      break;

    case Statement::STATEMENT_SEND:
      {
	Node* sent_node = Node::make_node(s->send_statement()->val());
	this->assign(this->context_->sink(), sent_node);
      }
      break;

    case Statement::STATEMENT_DEFER:
      if (this->context_->loop_depth() == 1)
        {
          // Defer statement may need to allocate a thunk. When it is
          // not inside a loop, this can be stack allocated, as it
          // runs before the function finishes.
          Node* n = Node::make_node(s);
          n->set_encoding(Node::ESCAPE_NONE);
          break;
        }
      // fallthrough

    case Statement::STATEMENT_GO:
      {
	// Defer f(x) or go f(x).
	// Both f and x escape to the heap.
	Thunk_statement* thunk = s->thunk_statement();
	if (thunk->call()->call_expression() == NULL)
	  break;

	Call_expression* call = thunk->call()->call_expression();
	Node* func_node = Node::make_node(call->fn());
	this->assign(this->context_->sink(), func_node);
	if (call->args() != NULL)
	  {
	    for (Expression_list::const_iterator p = call->args()->begin();
		 p != call->args()->end();
		 ++p)
	      {
		Node* arg_node = Node::make_node(*p);
		this->assign(this->context_->sink(), arg_node);
	      }
	  }
      }
      break;

    default:
      break;
    }
  return TRAVERSE_SKIP_COMPONENTS;
}

// Helper function to emit moved-to-heap diagnostics.

static void
move_to_heap(Gogo* gogo, Expression *expr)
{
  Named_object* no;
  if (expr->var_expression() != NULL)
    no = expr->var_expression()->named_object();
  else if (expr->enclosed_var_expression() != NULL)
    no = expr->enclosed_var_expression()->variable();
  else
    return;

  if ((no->is_variable()
       && !no->var_value()->is_global())
      || no->is_result_variable())
    {
      Node* n = Node::make_node(expr);
      if (gogo->debug_escape_level() != 0)
        go_inform(n->definition_location(),
                  "moved to heap: %s",
                  n->ast_format(gogo).c_str());
      if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
        go_error_at(expr->location(),
                    "%s escapes to heap, not allowed in runtime",
                    n->ast_format(gogo).c_str());
    }
}

// Model expressions within a function as assignments and flows between nodes.

int
Escape_analysis_assign::expression(Expression** pexpr)
{
  Gogo* gogo = this->context_->gogo();
  int debug_level = gogo->debug_escape_level();

  // Big stuff escapes unconditionally.
  Node* n = Node::make_node(*pexpr);
  if ((n->encoding() & ESCAPE_MASK) != int(Node::ESCAPE_HEAP)
      && n->is_big(this->context_))
    {
      if (debug_level > 1)
	go_inform((*pexpr)->location(), "%s too large for stack",
                  n->ast_format(gogo).c_str());
      move_to_heap(gogo, *pexpr);
      n->set_encoding(Node::ESCAPE_HEAP);
      (*pexpr)->address_taken(true);
      this->assign(this->context_->sink(), n);
    }

  if ((*pexpr)->func_expression() == NULL)
    (*pexpr)->traverse_subexpressions(this);

  if (debug_level > 1)
    {
      Node* n = Node::make_node(*pexpr);
      std::string fn_name = this->context_->current_function_name();
      go_inform((*pexpr)->location(), "[%d] %s esc: %s",
		this->context_->loop_depth(), fn_name.c_str(),
		n->ast_format(gogo).c_str());
    }

  switch ((*pexpr)->classification())
    {
    case Expression::EXPRESSION_CALL:
      {
	Call_expression* call = (*pexpr)->call_expression();
        if (call->is_builtin())
          {
            Builtin_call_expression* bce = call->builtin_call_expression();
            switch (bce->code())
              {
              case Builtin_call_expression::BUILTIN_PANIC:
                {
                  // Argument could leak through recover.
                  Node* panic_arg = Node::make_node(call->args()->front());
                  this->assign(this->context_->sink(), panic_arg);
                }
                break;

              case Builtin_call_expression::BUILTIN_APPEND:
                {
                  // The contents being appended leak.
                  if (call->is_varargs())
                    {
                      // append(slice1, slice2...) -- slice2 itself does not escape, but contents do
                      Node* appended = Node::make_node(call->args()->back());
                      this->assign_deref(this->context_->sink(), appended);
                      if (debug_level > 2)
                        go_inform((*pexpr)->location(),
                                  "special treatment of append(slice1, slice2...)");
                    }
                  else
                    {
                      for (Expression_list::const_iterator pa =
                             call->args()->begin() + 1;
                           pa != call->args()->end();
                           ++pa)
                        {
                          Node* arg = Node::make_node(*pa);
                          this->assign(this->context_->sink(), arg);
                        }
                    }

                  // The content of the original slice leaks as well.
                  Node* appendee = Node::make_node(call->args()->front());
                  this->assign_deref(this->context_->sink(), appendee);
                }
                break;

              case Builtin_call_expression::BUILTIN_COPY:
                {
                  // Lose track of the copied content.
                  Node* copied = Node::make_node(call->args()->back());
                  this->assign_deref(this->context_->sink(), copied);
                }
                break;

              default:
                break;
              }
            break;
          }
	Func_expression* fe = call->fn()->func_expression();
	if (fe != NULL && fe->is_runtime_function())
	  {
	    switch (fe->runtime_code())
	      {
	      case Runtime::MAKECHAN:
	      case Runtime::MAKECHAN64:
	      case Runtime::MAKEMAP:
	      case Runtime::MAKESLICE:
	      case Runtime::MAKESLICE64:
                this->context_->track(n);
		break;

              case Runtime::MAPASSIGN:
                {
                  // Map key escapes. The last argument is the address
                  // of the key.
                  Node* key_node = Node::make_node(call->args()->back());
                  this->assign_deref(this->context_->sink(), key_node);
                }
                break;

              case Runtime::IFACEE2T2:
              case Runtime::IFACEI2T2:
                {
                  // x, ok = v.(T), where T is non-pointer non-interface,
                  // is lowered to
                  // ok = IFACEI2T2(type, v, (void*)&tmp_x)
                  // Here v flows to tmp_x.
                  // Note: other IFACEX2Y2 returns the conversion result.
                  // Those are handled in ::assign.
                  Node* src_node = Node::make_node(call->args()->at(1));
                  Node* dst_node;
                  Expression* arg2 = call->args()->at(2);
                  // Try to pull tmp_x out of the arg2 expression, and let v
                  // flows into it, instead of simply dereference arg2,
                  // which looks like dereference of an arbitrary pointer
                  // and causes v immediately escape.
                  // The expression form matches statement.cc,
                  // Tuple_type_guard_assignment_statement::lower_to_object_type.
                  Unary_expression* ue =
                    (arg2->conversion_expression() != NULL
                     ? arg2->conversion_expression()->expr()->unary_expression()
                     : arg2->unary_expression());
                  if (ue != NULL && ue->op() == OPERATOR_AND)
                    {
                      if (!ue->operand()->type()->has_pointer())
                        // Don't bother flowing non-pointer.
                        break;
                      dst_node = Node::make_node(ue->operand());
                    }
                  else
                    dst_node = this->context_->add_dereference(Node::make_node(arg2));
                  this->assign(dst_node, src_node);
                }
                break;

	      default:
		break;
	      }
	  }
        else
          this->call(call);
      }
      break;

    case Expression::EXPRESSION_ALLOCATION:
      // This is Runtime::NEW.
      this->context_->track(n);
      break;

    case Expression::EXPRESSION_STRING_CONCAT:
      this->context_->track(n);
      break;

    case Expression::EXPRESSION_CONVERSION:
      {
	Type_conversion_expression* tce = (*pexpr)->conversion_expression();
        Type* ft = tce->expr()->type();
        Type* tt = tce->type();
        if ((ft->is_string_type() && tt->is_slice_type())
            || (ft->is_slice_type() && tt->is_string_type())
            || (ft->integer_type() != NULL && tt->is_string_type()))
          {
            // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
            this->context_->track(n);
            break;
          }
	Node* tce_node = Node::make_node(tce);
	Node* converted = Node::make_node(tce->expr());
	this->context_->track(tce_node);

	this->assign(tce_node, converted);
      }
      break;

    case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION:
    case Expression::EXPRESSION_SLICE_CONSTRUCTION:
      {
	Node* array_node = Node::make_node(*pexpr);
	if ((*pexpr)->slice_literal() != NULL)
	  this->context_->track(array_node);

	Expression_list* vals = ((*pexpr)->slice_literal() != NULL
				 ? (*pexpr)->slice_literal()->vals()
				 : (*pexpr)->array_literal()->vals());

	if (vals != NULL)
	  {
	    // Connect the array to its values.
	    for (Expression_list::const_iterator p = vals->begin();
		 p != vals->end();
		 ++p)
	      if ((*p) != NULL)
		this->assign(array_node, Node::make_node(*p));
	  }
      }
      break;

    case Expression::EXPRESSION_STRUCT_CONSTRUCTION:
      {
	Node* struct_node = Node::make_node(*pexpr);
	Expression_list* vals = (*pexpr)->struct_literal()->vals();
	if (vals != NULL)
	  {
	    // Connect the struct to its values.
	    for (Expression_list::const_iterator p = vals->begin();
		 p != vals->end();
		 ++p)
	      {
		if ((*p) != NULL)
		  this->assign(struct_node, Node::make_node(*p));
	      }
	  }
      }
      break;

    case Expression::EXPRESSION_HEAP:
      {
	Node* pointer_node = Node::make_node(*pexpr);
	Node* lit_node = Node::make_node((*pexpr)->heap_expression()->expr());
	this->context_->track(pointer_node);

	// Connect pointer node to literal node; if the pointer node escapes, so
	// does the literal node.
	this->assign(pointer_node, lit_node);
      }
      break;

    case Expression::EXPRESSION_BOUND_METHOD:
      {
	Node* bound_node = Node::make_node(*pexpr);
	this->context_->track(bound_node);

	Expression* obj = (*pexpr)->bound_method_expression()->first_argument();
	Node* obj_node = Node::make_node(obj);

	// A bound method implies the receiver will be used outside of the
	// lifetime of the method in some way.  We lose track of the receiver.
	this->assign(this->context_->sink(), obj_node);
      }
      break;

    case Expression::EXPRESSION_MAP_CONSTRUCTION:
      {
	Map_construction_expression* mce = (*pexpr)->map_literal();
	Node* map_node = Node::make_node(mce);
	this->context_->track(map_node);

	// All keys and values escape to memory.
	if (mce->vals() != NULL)
	  {
	    for (Expression_list::const_iterator p = mce->vals()->begin();
		 p != mce->vals()->end();
		 ++p)
	      {
		if ((*p) != NULL)
		  this->assign(this->context_->sink(), Node::make_node(*p));
	      }
	  }
      }
      break;

    case Expression::EXPRESSION_FUNC_REFERENCE:
      {
	Func_expression* fe = (*pexpr)->func_expression();
	if (fe->closure() != NULL)
	  {
	    // Connect captured variables to the closure.
	    Node* closure_node = Node::make_node(fe);
	    this->context_->track(closure_node);

	    // A closure expression already exists as the heap expression:
	    // &struct{f func_code, v []*Variable}{...}.
	    // Link closure to the addresses of the variables enclosed.
	    Heap_expression* he = fe->closure()->heap_expression();
	    Struct_construction_expression* sce = he->expr()->struct_literal();

	    // First field is function code, other fields are variable
	    // references.
	    Expression_list::const_iterator p = sce->vals()->begin();
	    ++p;
	    for (; p != sce->vals()->end(); ++p)
	      {
		Node* enclosed_node = Node::make_node(*p);
		this->context_->track(enclosed_node);
		this->assign(closure_node, enclosed_node);
	      }
	  }
      }
      break;

    case Expression::EXPRESSION_UNARY:
      {
	Expression* operand = (*pexpr)->unary_expression()->operand();

        if ((*pexpr)->unary_expression()->op() == OPERATOR_AND)
          {
            this->context_->track(n);

            Named_object* var = NULL;
            if (operand->var_expression() != NULL)
              var = operand->var_expression()->named_object();
            else if (operand->enclosed_var_expression() != NULL)
              var = operand->enclosed_var_expression()->variable();

            if (var != NULL
                && ((var->is_variable() && var->var_value()->is_parameter())
                    || var->is_result_variable()))
              {
                Node::Escape_state* addr_state = n->state(this->context_, NULL);
                addr_state->loop_depth = 1;
                break;
              }
          }

        if ((*pexpr)->unary_expression()->op() != OPERATOR_AND
            && (*pexpr)->unary_expression()->op() != OPERATOR_MULT)
          break;

        // For &x and *x, use the loop depth of x if known.
        Node::Escape_state* expr_state = n->state(this->context_, NULL);
        Node* operand_node = Node::make_node(operand);
        Node::Escape_state* operand_state = operand_node->state(this->context_, NULL);
        if (operand_state->loop_depth != 0)
          expr_state->loop_depth = operand_state->loop_depth;
      }
      break;

    case Expression::EXPRESSION_ARRAY_INDEX:
      {
        Array_index_expression* aie = (*pexpr)->array_index_expression();

        // Propagate the loopdepth to element.
        Node* array_node = Node::make_node(aie->array());
        Node::Escape_state* elem_state = n->state(this->context_, NULL);
        Node::Escape_state* array_state = array_node->state(this->context_, NULL);
        elem_state->loop_depth = array_state->loop_depth;

        if (aie->end() != NULL && !aie->array()->type()->is_slice_type())
          {
            // Slicing an array. This effectively takes the address of the array.
            Expression* addr = Expression::make_unary(OPERATOR_AND, aie->array(),
                                                      aie->location());
            Node* addr_node = Node::make_node(addr);
            n->set_child(addr_node);
            this->context_->track(addr_node);

            Node::Escape_state* addr_state = addr_node->state(this->context_, NULL);
            addr_state->loop_depth = array_state->loop_depth;
          }
      }
      break;

    case Expression::EXPRESSION_FIELD_REFERENCE:
      {
        // Propagate the loopdepth to field.
        Node* struct_node =
          Node::make_node((*pexpr)->field_reference_expression()->expr());
        Node::Escape_state* field_state = n->state(this->context_, NULL);
        Node::Escape_state* struct_state = struct_node->state(this->context_, NULL);
        field_state->loop_depth = struct_state->loop_depth;
      }
      break;

    default:
      break;
    }
  return TRAVERSE_SKIP_COMPONENTS;
}

// Model calls within a function as assignments and flows between arguments
// and results.

void
Escape_analysis_assign::call(Call_expression* call)
{
  Gogo* gogo = this->context_->gogo();
  int debug_level = gogo->debug_escape_level();

  Func_expression* fn = call->fn()->func_expression();
  Function_type* fntype = call->get_function_type();
  bool indirect = false;

  // Interface method calls or closure calls are indirect calls.
  if (fntype == NULL
      || (fntype->is_method()
	  && fntype->receiver()->type()->interface_type() != NULL)
      || fn == NULL
      || (fn->named_object()->is_function()
	  && fn->named_object()->func_value()->enclosing() != NULL))
    indirect = true;

  Node* call_node = Node::make_node(call);
  std::vector<Node*> arg_nodes;
  if (call->fn()->interface_field_reference_expression() != NULL)
    {
      Interface_field_reference_expression* ifre =
	call->fn()->interface_field_reference_expression();
      Node* field_node = Node::make_node(ifre->expr());
      arg_nodes.push_back(field_node);
    }

  if (call->args() != NULL)
    {
      for (Expression_list::const_iterator p = call->args()->begin();
	   p != call->args()->end();
	   ++p)
	arg_nodes.push_back(Node::make_node(*p));
    }

  if (indirect)
    {
      // We don't know what happens to the parameters through indirect calls.
      // Be conservative and assume they all flow to theSink.
      for (std::vector<Node*>::iterator p = arg_nodes.begin();
           p != arg_nodes.end();
           ++p)
	{
	  if (debug_level > 2)
	    go_inform(call->location(),
		      "esccall:: indirect call <- %s, untracked",
		      (*p)->ast_format(gogo).c_str());
	  this->assign(this->context_->sink(), *p);
	}

      this->context_->init_retvals(call_node, fntype);

      // It could be a closure call that returns captured variable.
      // Model this by flowing the func expression to result.
      // See issue #14409.
      Node* fn_node = Node::make_node(call->fn());
      std::vector<Node*> retvals = call_node->state(this->context_, NULL)->retvals;
      for (std::vector<Node*>::const_iterator p = retvals.begin();
           p != retvals.end();
           ++p)
        this->assign_deref(*p, fn_node);

      return;
    }

  // If FN is an untagged function.
  if (fn != NULL
      && fn->named_object()->is_function()
      && !fntype->is_tagged())
    {
      if (debug_level > 2)
	go_inform(call->location(), "esccall:: %s in recursive group",
		  call_node->ast_format(gogo).c_str());

      Function* f = fn->named_object()->func_value();
      const Bindings* callee_bindings = f->block()->bindings();
      Function::Results* results = f->result_variables();
      if (results != NULL)
	{
	  // Setup output list on this call node.
	  Node::Escape_state* state = call_node->state(this->context_, NULL);
	  for (Function::Results::const_iterator p1 = results->begin();
	       p1 != results->end();
	       ++p1)
	    {
	      Node* result_node = Node::make_node(*p1);
	      state->retvals.push_back(result_node);
	    }
	}

      std::vector<Node*>::iterator p = arg_nodes.begin();
      if (fntype->is_method())
	{
	  std::string rcvr_name = fntype->receiver()->name();
	  if (rcvr_name.empty() || Gogo::is_sink_name(rcvr_name)
              || !fntype->receiver()->type()->has_pointer())
	    ;
	  else
	    {
	      Named_object* rcvr_no =
		callee_bindings->lookup_local(fntype->receiver()->name());
	      go_assert(rcvr_no != NULL);
	      Node* rcvr_node = Node::make_node(rcvr_no);
              if (fntype->receiver()->type()->points_to() == NULL
                  && (*p)->expr()->type()->points_to() != NULL)
                // This is a call to a value method that has been lowered into a call
                // to a pointer method.  Gccgo generates a pointer method for all
                // method calls and takes the address of the value passed as the
                // receiver then immediately dereferences it within the function.
                // In this case, the receiver address does not escape; its content
                // flows to the call.
                this->assign_deref(rcvr_node, *p);
              else
                this->assign(rcvr_node, *p);
	    }
	  ++p;
	}

      const Typed_identifier_list* til = fntype->parameters();
      if (til != NULL)
	{
	  for (Typed_identifier_list::const_iterator p1 = til->begin();
	       p1 != til->end();
	       ++p1, ++p)
	    {
	      if (p1->name().empty() || Gogo::is_sink_name(p1->name()))
		continue;

	      Named_object* param_no =
		callee_bindings->lookup_local(p1->name());
	      go_assert(param_no != NULL);
	      Expression* arg = (*p)->expr();
	      if (arg->var_expression() != NULL
		  && arg->var_expression()->named_object() == param_no)
		continue;

	      Node* param_node = Node::make_node(param_no);
	      this->assign(param_node, *p);
	    }

	  for (; p != arg_nodes.end(); ++p)
	    {
	      if (debug_level > 2)
		go_inform(call->location(), "esccall:: ... <- %s, untracked",
			  (*p)->ast_format(gogo).c_str());
	      this->assign(this->context_->sink(), *p);
	    }
	}

      return;
    }

  if (debug_level > 2)
    go_inform(call->location(), "esccall:: %s not recursive",
	      call_node->ast_format(gogo).c_str());

  Node::Escape_state* call_state = call_node->state(this->context_, NULL);
  if (!call_state->retvals.empty())
    go_error_at(Linemap::unknown_location(),
		"esc already decorated call %s",
		call_node->ast_format(gogo).c_str());
  this->context_->init_retvals(call_node, fntype);

  // Receiver.
  std::vector<Node*>::iterator p = arg_nodes.begin();
  if (fntype->is_method()
      && p != arg_nodes.end())
    {
      // First argument to call will be the receiver.
      std::string* note = fntype->receiver()->note();
      if (fntype->receiver()->type()->points_to() == NULL
          && (*p)->expr()->type()->points_to() != NULL)
        // This is a call to a value method that has been lowered into a call
        // to a pointer method.  Gccgo generates a pointer method for all
        // method calls and takes the address of the value passed as the
        // receiver then immediately dereferences it within the function.
        // In this case, the receiver address does not escape; its content
        // flows to the call.
        this->assign_from_note(note, call_state->retvals,
                               this->context_->add_dereference(*p));
      else
	{
	  if (!Type::are_identical(fntype->receiver()->type(),
			       (*p)->expr()->type(), true, NULL))
	    {
	      // This will be converted later, preemptively track it instead
	      // of its conversion expression which will show up in a later pass.
	      this->context_->track(*p);
	    }
	  this->assign_from_note(note, call_state->retvals, *p);
	}
      p++;
    }

  const Typed_identifier_list* til = fntype->parameters();
  if (til != NULL)
    {
      for (Typed_identifier_list::const_iterator pn = til->begin();
	   pn != til->end() && p != arg_nodes.end();
	   ++pn, ++p)
	{
	  if (!Type::are_identical(pn->type(), (*p)->expr()->type(),
				   true, NULL))
	    {
	      // This will be converted later, preemptively track it instead
	      // of its conversion expression which will show up in a later pass.
	      this->context_->track(*p);
	    }

	  Type* t = pn->type();
	  if (t != NULL
	      && t->has_pointer())
	    {
	      std::string* note = pn->note();
	      int enc = this->assign_from_note(note, call_state->retvals, *p);
	      if (enc == Node::ESCAPE_NONE
		  && !call->is_deferred()
		  && !call->is_concurrent())
		{
                  // TODO(cmang): Mark the argument as strictly non-escaping?
                  // In the gc compiler this is for limiting the lifetime of
                  // temporaries. We probably don't need this?
		}
	    }
	}

      for (; p != arg_nodes.end(); ++p)
	{
	  if (debug_level > 2)
	    go_inform(call->location(), "esccall:: ... <- %s, untracked",
                      (*p)->ast_format(gogo).c_str());
	  this->assign(this->context_->sink(), *p);
	}
    }
}

// Model the assignment of DST to SRC.
// Assert that SRC somehow gets assigned to DST.
// DST might need to be examined for evaluations that happen inside of it.
// For example, in [DST]*f(x) = [SRC]y, we lose track of the indirection and
// DST becomes the sink in our model.

void
Escape_analysis_assign::assign(Node* dst, Node* src)
{
  Gogo* gogo = this->context_->gogo();
  int debug_level = gogo->debug_escape_level();
  if (debug_level > 1)
    go_inform(dst->location(), "[%d] %s escassign: %s(%s)[%s] = %s(%s)[%s]",
	      this->context_->loop_depth(),
	      strip_packed_prefix(gogo, this->context_->current_function_name()).c_str(),
	      dst->ast_format(gogo).c_str(), dst->details().c_str(),
	      dst->op_format().c_str(),
	      src->ast_format(gogo).c_str(), src->details().c_str(),
	      src->op_format().c_str());

  if (dst->is_indirect())
    // Lose track of the dereference.
    dst = this->context_->sink();
  else if (dst->expr() != NULL)
    {
      // Analyze the lhs of the assignment.
      // Replace DST with this->context_->sink() if we can't track it.
      Expression* e = dst->expr();
      switch (e->classification())
        {
	case Expression::EXPRESSION_VAR_REFERENCE:
	  {
	    // If DST is a global variable, we have no way to track it.
	    Named_object* var = e->var_expression()->named_object();
	    if (var->is_variable() && var->var_value()->is_global())
	      dst = this->context_->sink();
	  }
	  break;

	case Expression::EXPRESSION_FIELD_REFERENCE:
	  {
	    Expression* strct = e->field_reference_expression()->expr();
	    if (strct->heap_expression() != NULL)
	      {
		// When accessing the field of a struct reference, we lose
		// track of the indirection.
		dst = this->context_->sink();
		break;
	      }

	    // Treat DST.x = SRC as if it were DST = SRC.
	    Node* struct_node = Node::make_node(strct);
	    this->assign(struct_node, src);
	    return;
	  }

	case Expression::EXPRESSION_ARRAY_INDEX:
	  {
	    Array_index_expression* are = e->array_index_expression();
	    if (!are->array()->type()->is_slice_type())
	      {
		// Treat DST[i] = SRC as if it were DST = SRC if DST if a fixed
		// array.
		Node* array_node = Node::make_node(are->array());
		this->assign(array_node, src);
		return;
	      }

	    // Lose track of the slice dereference.
	    dst = this->context_->sink();
	  }
	  break;

	case Expression::EXPRESSION_UNARY:
	  // Lose track of the dereference.
	  if (e->unary_expression()->op() == OPERATOR_MULT)
	    dst = this->context_->sink();
	  break;

	case Expression::EXPRESSION_MAP_INDEX:
	  {
	    // Lose track of the map's key and value.
	    Expression* index = e->map_index_expression()->index();
	    Node* index_node = Node::make_node(index);
	    this->assign(this->context_->sink(), index_node);

	    dst = this->context_->sink();
	  }
	  break;

        case Expression::EXPRESSION_TEMPORARY_REFERENCE:
          {
            // Temporary is tracked through the underlying Temporary_statement.
            Temporary_statement* t =
	      dst->expr()->temporary_reference_expression()->statement();
	    if (t->value_escapes())
	      dst = this->context_->sink();
	    else
	      dst = Node::make_node(t);
          }
          break;

	default:
	  // TODO(cmang): Add debugging info here: only a few expressions
	  // should leave DST unmodified.
	  break;
        }
    }

  if (src->object() != NULL)
    this->flows(dst, src);
  else if (src->is_indirect())
    this->flows(dst, src);
  else if (src->expr() != NULL)
    {
      Expression* e = src->expr();
      switch (e->classification())
        {
	case Expression::EXPRESSION_VAR_REFERENCE:
        case Expression::EXPRESSION_ENCLOSED_VAR_REFERENCE:
	  // DST = var
	case Expression::EXPRESSION_HEAP:
	  // DST = &T{...}.
	case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION:
	case Expression::EXPRESSION_SLICE_CONSTRUCTION:
	  // DST = [...]T{...}.
	case Expression::EXPRESSION_MAP_CONSTRUCTION:
	  // DST = map[T]V{...}.
	case Expression::EXPRESSION_STRUCT_CONSTRUCTION:
	  // DST = T{...}.
	case Expression::EXPRESSION_ALLOCATION:
	  // DST = new(T).
	case Expression::EXPRESSION_BOUND_METHOD:
	  // DST = x.M.
        case Expression::EXPRESSION_STRING_CONCAT:
          // DST = str1 + str2
	  this->flows(dst, src);
	  break;

	case Expression::EXPRESSION_UNSAFE_CONVERSION:
	  {
	    Expression* underlying = e->unsafe_conversion_expression()->expr();
	    Node* underlying_node = Node::make_node(underlying);
	    this->assign(dst, underlying_node);
	  }
	  break;

	case Expression::EXPRESSION_CALL:
	  {
	    Call_expression* call = e->call_expression();
            if (call->is_builtin())
              {
                Builtin_call_expression* bce = call->builtin_call_expression();
                if (bce->code() == Builtin_call_expression::BUILTIN_APPEND)
                  {
                    // Append returns the first argument.
                    // The subsequent arguments are already leaked because
                    // they are operands to append.
                    Node* appendee = Node::make_node(call->args()->front());
                    this->assign(dst, appendee);
                  }
                break;
              }
	    Func_expression* fe = call->fn()->func_expression();
	    if (fe != NULL && fe->is_runtime_function())
	      {
		switch (fe->runtime_code())
		  {
		  case Runtime::MAKECHAN:
		  case Runtime::MAKECHAN64:
		  case Runtime::MAKEMAP:
		  case Runtime::MAKESLICE:
		  case Runtime::MAKESLICE64:
		    // DST = make(...).
                    this->flows(dst, src);
                    break;

		  default:
		    break;
		  }
		break;
	      }
	    else if (fe != NULL
		     && fe->named_object()->is_function()
		     && fe->named_object()->func_value()->is_method()
		     && (call->is_deferred()
			 || call->is_concurrent()))
	      {
		// For a method call thunk, lose track of the call and treat it
		// as if DST = RECEIVER.
		Node* rcvr_node = Node::make_node(call->args()->front());
		this->assign(dst, rcvr_node);
		break;
	      }

            // Result flows to dst.
            Node* call_node = Node::make_node(e);
            Node::Escape_state* call_state = call_node->state(this->context_, NULL);
            std::vector<Node*> retvals = call_state->retvals;
            for (std::vector<Node*>::const_iterator p = retvals.begin();
                 p != retvals.end();
                 ++p)
              this->flows(dst, *p);
	  }
	  break;

        case Expression::EXPRESSION_CALL_RESULT:
          {
            Call_result_expression* cre = e->call_result_expression();
            Call_expression* call = cre->call()->call_expression();
            if (call->is_builtin())
              break;
            if (call->fn()->func_expression() != NULL
                && call->fn()->func_expression()->is_runtime_function())
              {
                switch (call->fn()->func_expression()->runtime_code())
                  {
                  case Runtime::IFACEE2E2:
                  case Runtime::IFACEI2E2:
                  case Runtime::IFACEE2I2:
                  case Runtime::IFACEI2I2:
                  case Runtime::IFACEE2T2P:
                  case Runtime::IFACEI2T2P:
                    {
                      // x, ok = v.(T), where T is a pointer or interface,
                      // is lowered to
                      // x, ok = IFACEI2E2(v), or
                      // x, ok = IFACEI2I2(type, v)
                      // The last arg flows to the first result.
                      // Note: IFACEX2T2 has different signature, handled by
                      // ::expression.
                      if (cre->index() != 0)
                        break;
                      Node* arg_node = Node::make_node(call->args()->back());
                      this->assign(dst, arg_node);
                    }
                    break;

                  default:
                    break;
                  }
                break;
              }

            Node* call_node = Node::make_node(call);
            Node* ret_node = call_node->state(context_, NULL)->retvals[cre->index()];
            this->assign(dst, ret_node);
          }
          break;

	case Expression::EXPRESSION_FUNC_REFERENCE:
	  if (e->func_expression()->closure() != NULL)
            this->flows(dst, src);
	  break;

        case Expression::EXPRESSION_CONVERSION:
          {
            Type_conversion_expression* tce = e->conversion_expression();
            Type* ft = tce->expr()->type();
            Type* tt = tce->type();
            if ((ft->is_string_type() && tt->is_slice_type())
                || (ft->is_slice_type() && tt->is_string_type())
                || (ft->integer_type() != NULL && tt->is_string_type()))
              {
                // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
                this->flows(dst, src);
                break;
              }
            // Conversion preserves input value.
            Expression* underlying = tce->expr();
            this->assign(dst, Node::make_node(underlying));
          }
          break;

	case Expression::EXPRESSION_FIELD_REFERENCE:
	  {
	    // A non-pointer can't escape from a struct.
	    if (!e->type()->has_pointer())
	      break;
	  }
	  // Fall through.

	case Expression::EXPRESSION_TYPE_GUARD:
	case Expression::EXPRESSION_ARRAY_INDEX:
	case Expression::EXPRESSION_STRING_INDEX:
	  {
	    Expression* left = NULL;
	    if (e->field_reference_expression() != NULL)
	      {
		left = e->field_reference_expression()->expr();
		if (left->unary_expression() != NULL
		    && left->unary_expression()->op() == OPERATOR_MULT)
		  {
		    // DST = (*x).f
		    this->flows(dst, src);
		    break;
		  }
	      }
	    else if (e->type_guard_expression() != NULL)
	      left = e->type_guard_expression()->expr();
	    else if (e->array_index_expression() != NULL)
	      {
		Array_index_expression* aie = e->array_index_expression();
		if (aie->end() != NULL)
                  // slicing
                  if (aie->array()->type()->is_slice_type())
                    left = aie->array();
                  else
                    {
                      // slicing an array
                      // The gc compiler has an implicit address operator.
                      go_assert(src->child() != NULL);
                      this->assign(dst, src->child());
                      break;
                    }
		else if (!aie->array()->type()->is_slice_type())
		  {
		    // Indexing an array preserves the input value.
		    Node* array_node = Node::make_node(aie->array());
		    this->assign(dst, array_node);
		    break;
		  }
		else
		  {
		    this->flows(dst, src);
		    break;
		  }
	      }
	    else if (e->string_index_expression() != NULL)
	      {
		String_index_expression* sie = e->string_index_expression();
		if (e->type()->is_string_type())
                  // slicing
		  left = sie->string();
		else
		  {
		    this->flows(dst, src);
		    break;
		  }
	      }
	    go_assert(left != NULL);

	    // Conversions, field access, and slicing all preserve the input
	    // value.
	    Node* left_node = Node::make_node(left);
	    this->assign(dst, left_node);
	  }
	  break;

	case Expression::EXPRESSION_BINARY:
	  {
	    switch (e->binary_expression()->op())
	      {
	      case OPERATOR_PLUS:
	      case OPERATOR_MINUS:
	      case OPERATOR_XOR:
              case OPERATOR_OR:
	      case OPERATOR_MULT:
	      case OPERATOR_DIV:
	      case OPERATOR_MOD:
	      case OPERATOR_LSHIFT:
	      case OPERATOR_RSHIFT:
	      case OPERATOR_AND:
	      case OPERATOR_BITCLEAR:
		{
		  Node* left = Node::make_node(e->binary_expression()->left());
		  this->assign(dst, left);
		  Node* right = Node::make_node(e->binary_expression()->right());
		  this->assign(dst, right);
		}
		break;

	      default:
		break;
	      }
	  }
	  break;

	case Expression::EXPRESSION_UNARY:
	  {
	    switch (e->unary_expression()->op())
	      {
	      case OPERATOR_PLUS:
	      case OPERATOR_MINUS:
	      case OPERATOR_XOR:
		{
		    Node* op_node =
		      Node::make_node(e->unary_expression()->operand());
		    this->assign(dst, op_node);
		}
		break;

	      case OPERATOR_MULT:
		// DST = *x
	      case OPERATOR_AND:
		// DST = &x
		this->flows(dst, src);
		break;

	      default:
		break;
	      }
	  }
	  break;

	case Expression::EXPRESSION_TEMPORARY_REFERENCE:
	  {
	    Statement* temp = e->temporary_reference_expression()->statement();
            this->assign(dst, Node::make_node(temp));
	  }
	  break;

	default:
	  // TODO(cmang): Add debug info here; this should not be reachable.
	  // For now, just to be conservative, we'll just say dst flows to src.
	  break;
	}
    }
  else if (src->statement() != NULL && src->statement()->temporary_statement() != NULL)
    this->flows(dst, src);
}

// Model the assignment of DST to an indirection of SRC.

void
Escape_analysis_assign::assign_deref(Node* dst, Node* src)
{
  if (src->expr() != NULL)
    {
      switch (src->expr()->classification())
        {
	case Expression::EXPRESSION_BOOLEAN:
	case Expression::EXPRESSION_STRING:
	case Expression::EXPRESSION_INTEGER:
	case Expression::EXPRESSION_FLOAT:
	case Expression::EXPRESSION_COMPLEX:
	case Expression::EXPRESSION_NIL:
	case Expression::EXPRESSION_IOTA:
	  // No need to try indirections on literal values
	  // or numeric constants.
	  return;

	default:
	  break;
        }
    }

  this->assign(dst, this->context_->add_dereference(src));
}

// Model the input-to-output assignment flow of one of a function call's
// arguments, where the flow is encoded in NOTE.

int
Escape_analysis_assign::assign_from_note(std::string* note,
					 const std::vector<Node*>& dsts,
					 Node* src)
{
  int enc = Escape_note::parse_tag(note);
  if (src->expr() != NULL)
    {
      switch (src->expr()->classification())
        {
	case Expression::EXPRESSION_BOOLEAN:
	case Expression::EXPRESSION_STRING:
	case Expression::EXPRESSION_INTEGER:
	case Expression::EXPRESSION_FLOAT:
	case Expression::EXPRESSION_COMPLEX:
	case Expression::EXPRESSION_NIL:
	case Expression::EXPRESSION_IOTA:
	  // There probably isn't a note for a literal value.  Literal values
	  // usually don't escape unless we lost track of the value some how.
	  return enc;

	default:
	  break;
        }
    }

  if (this->context_->gogo()->debug_escape_level() > 2)
    go_inform(src->location(), "assignfromtag:: src=%s em=%s",
              src->ast_format(context_->gogo()).c_str(),
	      Escape_note::make_tag(enc).c_str());

  if (enc == Node::ESCAPE_UNKNOWN)
    {
      // Lost track of the value.
      this->assign(this->context_->sink(), src);
      return enc;
    }
  else if (enc == Node::ESCAPE_NONE)
    return enc;

  // If the content inside a parameter (reached via indirection) escapes to
  // the heap, mark it.
  if ((enc & ESCAPE_CONTENT_ESCAPES) != 0)
    this->assign(this->context_->sink(), this->context_->add_dereference(src));

  int save_enc = enc;
  enc >>= ESCAPE_RETURN_BITS;
  for (std::vector<Node*>::const_iterator p = dsts.begin();
       enc != 0 && p != dsts.end();
       ++p)
    {
      // Prefer the lowest-level path to the reference (for escape purposes).
      // Two-bit encoding (for example. 1, 3, and 4 bits are other options)
      //  01 = 0-level
      //  10 = 1-level, (content escapes),
      //  11 = 2-level, (content of content escapes).
      int bits = enc & ESCAPE_BITS_MASK_FOR_TAG;
      if (bits > 0)
	{
	  Node* n = src;
	  for (int i = 0; i < bits - 1; ++i)
	    {
	      // Encode level > 0 as indirections.
	      n = this->context_->add_dereference(n);
	    }
	  this->assign(*p, n);
	}
      enc >>= ESCAPE_BITS_PER_OUTPUT_IN_TAG;
    }

  // If there are too many outputs to fit in the tag, that is handled on the
  // encoding end as ESCAPE_HEAP, so there is no need to check here.
  return save_enc;
}

// Record the flow of SRC to DST in DST.

void
Escape_analysis_assign::flows(Node* dst, Node* src)
{
  // Don't bother capturing the flow from scalars.
  if (src->type() != NULL && !src->type()->has_pointer())
    return;

  // Don't confuse a blank identifier with the sink.
  if (dst->is_sink() && dst != this->context_->sink())
    return;

  Node::Escape_state* dst_state = dst->state(this->context_, NULL);
  Node::Escape_state* src_state = src->state(this->context_, NULL);
  if (dst == src
      || dst_state == src_state
      || dst_state->flows.find(src) != dst_state->flows.end())
    return;

  Gogo* gogo = this->context_->gogo();
  if (gogo->debug_escape_level() > 2)
    go_inform(Linemap::unknown_location(), "flows:: %s <- %s",
              dst->ast_format(gogo).c_str(), src->ast_format(gogo).c_str());

  if (dst_state->flows.empty())
    this->context_->add_dst(dst);

  dst_state->flows.insert(src);
}

// Build a connectivity graph between nodes in the function being analyzed.

void
Gogo::assign_connectivity(Escape_context* context, Named_object* fn)
{
  // Must be defined outside of this package.
  if (!fn->is_function())
    return;

  int save_depth = context->loop_depth();
  context->set_loop_depth(1);

  Escape_analysis_assign ea(context, fn);
  Function::Results* res = fn->func_value()->result_variables();
  if (res != NULL)
    {
      for (Function::Results::const_iterator p = res->begin();
	   p != res->end();
	   ++p)
	{
	  Node* res_node = Node::make_node(*p);
	  Node::Escape_state* res_state = res_node->state(context, fn);
          res_state->fn = fn;
	  res_state->loop_depth = 0;

	  // If this set of functions is recursive, we lose track of the return values.
	  // Just say that the result flows to the sink.
	  if (context->recursive())
	    ea.flows(context->sink(), res_node);
	}
    }

  const Bindings* callee_bindings = fn->func_value()->block()->bindings();
  Function_type* fntype = fn->func_value()->type();
  Typed_identifier_list* params = (fntype->parameters() != NULL
				   ? fntype->parameters()->copy()
				   : new Typed_identifier_list);
  if (fntype->receiver() != NULL)
    params->push_back(*fntype->receiver());

  for (Typed_identifier_list::const_iterator p = params->begin();
       p != params->end();
       ++p)
    {
      if (p->name().empty() || Gogo::is_sink_name(p->name()))
	continue;

      Named_object* param_no = callee_bindings->lookup_local(p->name());
      go_assert(param_no != NULL);
      Node* param_node = Node::make_node(param_no);
      Node::Escape_state* param_state = param_node->state(context, fn);
      param_state->fn = fn;
      param_state->loop_depth = 1;

      if (!p->type()->has_pointer())
        continue;

      // External function?  Parameters must escape unless //go:noescape is set.
      // TODO(cmang): Implement //go:noescape directive.
      if (fn->package() != NULL)
	param_node->set_encoding(Node::ESCAPE_HEAP);
      else
        {
          param_node->set_encoding(Node::ESCAPE_NONE);
          context->track(param_node);
        }
    }

  Escape_analysis_loop el;
  fn->func_value()->traverse(&el);

  fn->func_value()->traverse(&ea);
  context->set_loop_depth(save_depth);
}

class Escape_analysis_flood
{
 public:
  Escape_analysis_flood(Escape_context* context)
    : context_(context)
  { }

  // Use the escape information in dst to update the escape information in src
  // and src's upstream.
  void
  flood(Level, Node* dst, Node* src, int);

 private:
  // The escape context for the group of functions being flooded.
  Escape_context* context_;
};

// Whenever we hit a dereference node, the level goes up by one, and whenever
// we hit an address-of, the level goes down by one. as long as we're on a
// level > 0 finding an address-of just means we're following the upstream
// of a dereference, so this address doesn't leak (yet).
// If level == 0, it means the /value/ of this node can reach the root of this
// flood so if this node is an address-of, its argument should be marked as
// escaping iff its current function and loop depth are different from the
// flood's root.
// Once an object has been moved to the heap, all of its upstream should be
// considered escaping to the global scope.
// This is an implementation of gc/esc.go:escwalkBody.

void
Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
			     int extra_loop_depth)
{
  // No need to flood src if it is a literal.
  if (src->expr() != NULL)
    {
      switch (src->expr()->classification())
        {
	case Expression::EXPRESSION_BOOLEAN:
	case Expression::EXPRESSION_STRING:
	case Expression::EXPRESSION_INTEGER:
	case Expression::EXPRESSION_FLOAT:
	case Expression::EXPRESSION_COMPLEX:
	case Expression::EXPRESSION_NIL:
	case Expression::EXPRESSION_IOTA:
	  return;

	default:
	  break;
        }
    }

  Node::Escape_state* src_state = src->state(this->context_, NULL);
  if (src_state->flood_id == this->context_->flood_id())
    {
      // Esclevels are vectors, do not compare as integers,
      // and must use "min" of old and new to guarantee
      // convergence.
      level = level.min(src_state->level);
      if (level == src_state->level)
	{
	  // Have we been here already with an extraloopdepth,
	  // or is the extraloopdepth provided no improvement on
	  // what's already been seen?
	  if (src_state->max_extra_loop_depth >= extra_loop_depth
	      || src_state->loop_depth >= extra_loop_depth)
	    return;
	  src_state->max_extra_loop_depth = extra_loop_depth;
	}
    }
  else
    src_state->max_extra_loop_depth = -1;

  src_state->flood_id = this->context_->flood_id();
  src_state->level = level;
  int mod_loop_depth = std::max(extra_loop_depth, src_state->loop_depth);

  Gogo* gogo = this->context_->gogo();
  int debug_level = gogo->debug_escape_level();
  if (debug_level > 1)
    go_inform(Linemap::unknown_location(),
	      "escwalk: level:{%d %d} depth:%d "
	      "op=%s %s(%s) "
	      "scope:%s[%d] "
	      "extraloopdepth=%d",
	      level.value(), level.suffix_value(), this->context_->pdepth(),
	      src->op_format().c_str(),
	      src->ast_format(gogo).c_str(),
	      src->details().c_str(),
	      debug_function_name(src_state->fn).c_str(),
	      src_state->loop_depth,
	      extra_loop_depth);

  this->context_->increase_pdepth();

  // Input parameter flowing into output parameter?
  Named_object* src_no = NULL;
  if (src->expr() != NULL && src->expr()->var_expression() != NULL)
    src_no = src->expr()->var_expression()->named_object();
  else
    src_no = src->object();
  bool src_is_param = (src_no != NULL
		       && src_no->is_variable()
		       && src_no->var_value()->is_parameter());

  Named_object* dst_no = NULL;
  if (dst->expr() != NULL && dst->expr()->var_expression() != NULL)
    dst_no = dst->expr()->var_expression()->named_object();
  else
    dst_no = dst->object();
  bool dst_is_result = dst_no != NULL && dst_no->is_result_variable();
  Node::Escape_state* dst_state = dst->state(this->context_, NULL);

  if (src_is_param
      && dst_is_result
      && src_state->fn == dst_state->fn
      && (src->encoding() & ESCAPE_MASK) < int(Node::ESCAPE_HEAP)
      && dst->encoding() != Node::ESCAPE_HEAP)
    {
      // This case handles:
      // 1. return in
      // 2. return &in
      // 3. tmp := in; return &tmp
      // 4. return *in
      if (debug_level != 0)
	{
	  if (debug_level == 1)
	    go_inform(src->definition_location(),
		      "leaking param: %s to result %s level=%d",
		      src->ast_format(gogo).c_str(),
		      dst->ast_format(gogo).c_str(),
		      level.value());
	  else
	    go_inform(src->definition_location(),
		      "leaking param: %s to result %s level={%d %d}",
		      src->ast_format(gogo).c_str(),
		      dst->ast_format(gogo).c_str(),
		      level.value(), level.suffix_value());
	}

      if ((src->encoding() & ESCAPE_MASK) != Node::ESCAPE_RETURN)
	{
	  int enc =
	    Node::ESCAPE_RETURN | (src->encoding() & ESCAPE_CONTENT_ESCAPES);
	  src->set_encoding(enc);
	}

      int enc = Node::note_inout_flows(src->encoding(),
				       dst_no->result_var_value()->index(),
				       level);
      src->set_encoding(enc);

      // In gc/esc.go:escwalkBody, this is a goto to the label for recursively
      // flooding the connection graph.  Inlined here for convenience.
      level = level.copy();
      for (std::set<Node*>::const_iterator p = src_state->flows.begin();
	   p != src_state->flows.end();
	   ++p)
	this->flood(level, dst, *p, extra_loop_depth);
      return;
    }

  // If parameter content escape to heap, set ESCAPE_CONTENT_ESCAPES.
  // Note minor confusion around escape from pointer-to-struct vs
  // escape from struct.
  if (src_is_param
      && dst->encoding() == Node::ESCAPE_HEAP
      && (src->encoding() & ESCAPE_MASK) < int(Node::ESCAPE_HEAP)
      && level.value() > 0)
    {
      int enc =
	Node::max_encoding((src->encoding() | ESCAPE_CONTENT_ESCAPES),
			   Node::ESCAPE_NONE);
      src->set_encoding(enc);
      if (debug_level != 0)
	go_inform(src->definition_location(), "mark escaped content: %s",
		  src->ast_format(gogo).c_str());
    }

  // A src object leaks if its value or address is assigned to a dst object
  // in a different scope (at a different loop depth).
  bool src_leaks = (level.value() <= 0
		    && level.suffix_value() <= 0
		    && dst_state->loop_depth < mod_loop_depth);
  src_leaks = src_leaks || (level.value() <= 0
              && (dst->encoding() & ESCAPE_MASK) == Node::ESCAPE_HEAP);
  // old src encoding, used to prevent duplicate error messages
  int osrcesc = src->encoding();

  if (src_is_param
      && (src_leaks || dst_state->loop_depth < 0)
      && (src->encoding() & ESCAPE_MASK) < int(Node::ESCAPE_HEAP))
    {
      if (level.suffix_value() > 0)
	{
	  int enc =
	    Node::max_encoding((src->encoding() | ESCAPE_CONTENT_ESCAPES),
			       Node::ESCAPE_NONE);
	  src->set_encoding(enc);
	  if (debug_level != 0 && osrcesc != src->encoding())
	    go_inform(src->definition_location(), "leaking param content: %s",
		      src->ast_format(gogo).c_str());
	}
      else
	{
	  if (debug_level != 0)
	    go_inform(src->definition_location(), "leaking param: %s",
                      src->ast_format(gogo).c_str());
	  src->set_encoding(Node::ESCAPE_HEAP);
	}
    }
  else if (src->expr() != NULL)
    {
      Expression* e = src->expr();
      if (e->enclosed_var_expression() != NULL)
	{
	  if (src_leaks && debug_level != 0)
	    go_inform(src->location(), "leaking closure reference %s",
		      src->ast_format(gogo).c_str());

	  Node* enclosed_node =
	    Node::make_node(e->enclosed_var_expression()->variable());
	  this->flood(level, dst, enclosed_node, -1);
	}
      else if (e->heap_expression() != NULL
	  || (e->unary_expression() != NULL
	      && e->unary_expression()->op() == OPERATOR_AND))
	{
	  // Pointer literals and address-of expressions.
	  Expression* underlying;
	  if (e->heap_expression())
	    underlying = e->heap_expression()->expr();
	  else
	    underlying = e->unary_expression()->operand();
	  Node* underlying_node = Node::make_node(underlying);

	  // If the address leaks, the underyling object must be moved
	  // to the heap.
	  underlying->address_taken(src_leaks);
	  if (src_leaks)
	    {
	      src->set_encoding(Node::ESCAPE_HEAP);
              if (osrcesc != src->encoding())
                {
                  move_to_heap(gogo, underlying);
                  if (debug_level > 1)
                    go_inform(src->location(),
                              "%s escapes to heap, level={%d %d}, "
                              "dst.eld=%d, src.eld=%d",
                              src->ast_format(gogo).c_str(), level.value(),
                              level.suffix_value(), dst_state->loop_depth,
                              mod_loop_depth);
                  else if (debug_level > 0)
                    go_inform(src->location(), "%s escapes to heap",
                              src->ast_format(gogo).c_str());
                }

	      this->flood(level.decrease(), dst,
			  underlying_node, mod_loop_depth);
	      extra_loop_depth = mod_loop_depth;
	    }
	  else
	    {
	      // Decrease the level each time we take the address of the object.
	      this->flood(level.decrease(), dst, underlying_node, -1);
	    }
	}
      else if (e->slice_literal() != NULL)
	{
	  Slice_construction_expression* slice = e->slice_literal();
	  if (slice->vals() != NULL)
	    {
	      for (Expression_list::const_iterator p = slice->vals()->begin();
		   p != slice->vals()->end();
		   ++p)
		{
		  if ((*p) != NULL)
		    this->flood(level.decrease(), dst, Node::make_node(*p), -1);
		}
	    }
	  if (src_leaks)
	    {
	      src->set_encoding(Node::ESCAPE_HEAP);
	      if (debug_level != 0 && osrcesc != src->encoding())
		go_inform(src->location(), "%s escapes to heap",
			  src->ast_format(gogo).c_str());
	      extra_loop_depth = mod_loop_depth;
	    }
	}
      else if (e->call_expression() != NULL)
	{
	  Call_expression* call = e->call_expression();
          if (call->is_builtin())
            {
              Builtin_call_expression* bce = call->builtin_call_expression();
              if (bce->code() == Builtin_call_expression::BUILTIN_APPEND)
                {
                  // Propagate escape information to appendee.
                  Expression* appendee = call->args()->front();
                  this->flood(level, dst, Node::make_node(appendee), -1);
                }
            }
          else if (call->fn()->func_expression() != NULL
                   && call->fn()->func_expression()->is_runtime_function())
            {
              switch (call->fn()->func_expression()->runtime_code())
                {
                case Runtime::MAKECHAN:
		case Runtime::MAKECHAN64:
                case Runtime::MAKEMAP:
                case Runtime::MAKESLICE:
                case Runtime::MAKESLICE64:
                  if (src_leaks)
                    {
                      src->set_encoding(Node::ESCAPE_HEAP);
                      if (debug_level != 0 && osrcesc != src->encoding())
                        go_inform(src->location(), "%s escapes to heap",
                                  src->ast_format(gogo).c_str());
                      extra_loop_depth = mod_loop_depth;
                    }
                  break;

                default:
                  break;
                }
            }
          else if (src_state->retvals.size() > 0)
            {
              // In this case a link went directly to a call, but should really go
              // to the dummy .outN outputs that were created for the call that
              // themselves link to the inputs with levels adjusted.
              // See e.g. #10466.
              // This can only happen with functions returning a single result.
              go_assert(src_state->retvals.size() == 1);
              if (debug_level > 2)
                go_inform(src->location(), "[%d] dst %s escwalk replace src: %s with %s",
                          this->context_->loop_depth(),
                          dst->ast_format(gogo).c_str(),
                          src->ast_format(gogo).c_str(),
                          src_state->retvals[0]->ast_format(gogo).c_str());
              src = src_state->retvals[0];
              src_state = src->state(this->context_, NULL);
            }
	}
      else if (e->allocation_expression() != NULL && src_leaks)
	{
	  // Calls to Runtime::NEW get lowered into an allocation expression.
	  src->set_encoding(Node::ESCAPE_HEAP);
	  if (debug_level != 0 && osrcesc != src->encoding())
	    go_inform(src->location(), "%s escapes to heap",
                      src->ast_format(gogo).c_str());
          extra_loop_depth = mod_loop_depth;
	}
      else if ((e->map_literal() != NULL
               || e->string_concat_expression() != NULL
               || (e->func_expression() != NULL && e->func_expression()->closure() != NULL)
               || e->bound_method_expression() != NULL)
               && src_leaks)
        {
          src->set_encoding(Node::ESCAPE_HEAP);
          if (debug_level != 0 && osrcesc != src->encoding())
            go_inform(src->location(), "%s escapes to heap",
                      src->ast_format(gogo).c_str());
          extra_loop_depth = mod_loop_depth;
        }
      else if (e->conversion_expression() != NULL && src_leaks)
        {
          Type_conversion_expression* tce = e->conversion_expression();
          Type* ft = tce->expr()->type();
          Type* tt = tce->type();
          if ((ft->is_string_type() && tt->is_slice_type())
              || (ft->is_slice_type() && tt->is_string_type())
              || (ft->integer_type() != NULL && tt->is_string_type()))
            {
              // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
              src->set_encoding(Node::ESCAPE_HEAP);
              if (debug_level != 0 && osrcesc != src->encoding())
                go_inform(src->location(), "%s escapes to heap",
                          src->ast_format(gogo).c_str());
              extra_loop_depth = mod_loop_depth;
            }
        }
      else if (e->array_index_expression() != NULL
               && !e->array_index_expression()->array()->type()->is_slice_type())
        {
          Array_index_expression* aie = e->array_index_expression();
          if (aie->end() != NULL)
            {
              // Slicing an array.
              // Flow its implicit address-of node to DST.
              this->flood(level, dst, src->child(), -1);
            }
          else
            {
              // Indexing an array.
              // An array element flowing to DST behaves like the array
              // flowing to DST.
              Expression* underlying = e->array_index_expression()->array();
              Node* underlying_node = Node::make_node(underlying);
              this->flood(level, dst, underlying_node, -1);
            }
        }
      else if ((e->field_reference_expression() != NULL
		&& e->field_reference_expression()->expr()->unary_expression() == NULL)
	       || e->type_guard_expression() != NULL
	       || (e->array_index_expression() != NULL
		   && e->array_index_expression()->end() != NULL)
	       || (e->string_index_expression() != NULL
		   && e->type()->is_string_type()))
	{
	  Expression* underlying;
	  if (e->field_reference_expression() != NULL)
	    underlying = e->field_reference_expression()->expr();
	  else if (e->type_guard_expression() != NULL)
	    underlying = e->type_guard_expression()->expr();
	  else if (e->array_index_expression() != NULL)
	    underlying = e->array_index_expression()->array();
	  else
	    underlying = e->string_index_expression()->string();

	  Node* underlying_node = Node::make_node(underlying);
	  this->flood(level, dst, underlying_node, -1);
	}
      else if ((e->field_reference_expression() != NULL
		&& e->field_reference_expression()->expr()->unary_expression() != NULL)
	       || e->array_index_expression() != NULL
	       || e->map_index_expression() != NULL
	       || (e->unary_expression() != NULL
		   && e->unary_expression()->op() == OPERATOR_MULT))
	{
	  Expression* underlying;
	  if (e->field_reference_expression() != NULL)
	    {
	      underlying = e->field_reference_expression()->expr();
	      underlying = underlying->unary_expression()->operand();
	    }
	  else if (e->array_index_expression() != NULL)
	    underlying = e->array_index_expression()->array();
	  else if (e->map_index_expression() != NULL)
	    underlying = e->map_index_expression()->map();
	  else
	    underlying = e->unary_expression()->operand();

	  // Increase the level for a dereference.
	  Node* underlying_node = Node::make_node(underlying);
	  this->flood(level.increase(), dst, underlying_node, -1);
	}
      else if (e->temporary_reference_expression() != NULL)
        {
          Statement* t = e->temporary_reference_expression()->statement();
          this->flood(level, dst, Node::make_node(t), -1);
        }
    }
  else if (src->is_indirect())
    // Increase the level for a dereference.
    this->flood(level.increase(), dst, src->child(), -1);

  level = level.copy();
  for (std::set<Node*>::const_iterator p = src_state->flows.begin();
       p != src_state->flows.end();
       ++p)
    this->flood(level, dst, *p, extra_loop_depth);

  this->context_->decrease_pdepth();
}

// Propagate escape information across the nodes modeled in this Analysis_set.
// This is an implementation of gc/esc.go:escflood.

void
Gogo::propagate_escape(Escape_context* context, Node* dst)
{
  if (dst->object() == NULL
      && (dst->expr() == NULL
          || (dst->expr()->var_expression() == NULL
              && dst->expr()->enclosed_var_expression() == NULL
              && dst->expr()->func_expression() == NULL)))
    return;

  Node::Escape_state* state = dst->state(context, NULL);
  Gogo* gogo = context->gogo();
  if (gogo->debug_escape_level() > 1)
    go_inform(Linemap::unknown_location(), "escflood:%d: dst %s scope:%s[%d]",
	      context->flood_id(), dst->ast_format(gogo).c_str(),
	      debug_function_name(state->fn).c_str(),
	      state->loop_depth);

  Escape_analysis_flood eaf(context);
  for (std::set<Node*>::const_iterator p = state->flows.begin();
       p != state->flows.end();
       ++p)
    {
      context->increase_flood_id();
      eaf.flood(Level::From(0), dst, *p, -1);
    }
}

class Escape_analysis_tag
{
 public:
  Escape_analysis_tag(Escape_context* context)
    : context_(context)
  { }

  // Add notes to the function's type about the escape information of its
  // input parameters.
  void
  tag(Named_object* fn);

 private:
  Escape_context* context_;
};

void
Escape_analysis_tag::tag(Named_object* fn)
{
  // External functions are assumed unsafe
  // unless //go:noescape is given before the declaration.
  if (fn->package() != NULL)
    return;

  if (fn->is_function_declaration())
    {
      Function_declaration* fdcl = fn->func_declaration_value();
      if ((fdcl->pragmas() & GOPRAGMA_NOESCAPE) != 0)
        {
          Function_type* fntype = fdcl->type();
          if (fntype->parameters() != NULL)
            {
              const Typed_identifier_list* til = fntype->parameters();
              int i = 0;
              for (Typed_identifier_list::const_iterator p = til->begin();
                   p != til->end();
                   ++p, ++i)
                if (p->type()->has_pointer())
                  fntype->add_parameter_note(i, Node::ESCAPE_NONE);
            }
        }
    }

  if (!fn->is_function())
    return;

  Function_type* fntype = fn->func_value()->type();
  Bindings* bindings = fn->func_value()->block()->bindings();

  if (fntype->is_method())
    {
      if (fntype->receiver()->name().empty()
          || Gogo::is_sink_name(fntype->receiver()->name()))
        // Unnamed receiver is not used in the function body, does not escape.
        fntype->add_receiver_note(Node::ESCAPE_NONE);
      else
        {
          Named_object* rcvr_no = bindings->lookup(fntype->receiver()->name());
          go_assert(rcvr_no != NULL);
          Node* rcvr_node = Node::make_node(rcvr_no);
          switch ((rcvr_node->encoding() & ESCAPE_MASK))
            {
            case Node::ESCAPE_NONE: // not touched by flood
            case Node::ESCAPE_RETURN:
              if (fntype->receiver()->type()->has_pointer())
                // Don't bother tagging for scalars.
                fntype->add_receiver_note(rcvr_node->encoding());
              break;

            case Node::ESCAPE_HEAP: // flooded, moved to heap.
              break;

            default:
              break;
            }
        }
    }

  int i = 0;
  if (fntype->parameters() != NULL)
    {
      const Typed_identifier_list* til = fntype->parameters();
      for (Typed_identifier_list::const_iterator p = til->begin();
	   p != til->end();
	   ++p, ++i)
	{
	  if (p->name().empty() || Gogo::is_sink_name(p->name()))
            {
              // Parameter not used in the function body, does not escape.
              if (p->type()->has_pointer())
                fntype->add_parameter_note(i, Node::ESCAPE_NONE);
              continue;
            }

	  Named_object* param_no = bindings->lookup(p->name());
	  go_assert(param_no != NULL);
	  Node* param_node = Node::make_node(param_no);
	  switch ((param_node->encoding() & ESCAPE_MASK))
	    {
	    case Node::ESCAPE_NONE: // not touched by flood
	    case Node::ESCAPE_RETURN:
	      if (p->type()->has_pointer())
		// Don't bother tagging for scalars.
		fntype->add_parameter_note(i, param_node->encoding());
	      break;

	    case Node::ESCAPE_HEAP: // flooded, moved to heap.
	      break;

	    default:
	      break;
	    }
	}
    }
  fntype->set_is_tagged();
}

// Tag each top-level function with escape information that will be used to
// retain analysis results across imports.

void
Gogo::tag_function(Escape_context* context, Named_object* fn)
{
  Escape_analysis_tag eat(context);
  eat.tag(fn);
}

// Reclaim memory of escape analysis Nodes.

void
Gogo::reclaim_escape_nodes()
{
  Node::reclaim_nodes();
}

void
Node::reclaim_nodes()
{
  for (std::map<Named_object*, Node*>::iterator p = Node::objects.begin();
       p != Node::objects.end();
       ++p)
    delete p->second;
  Node::objects.clear();

  for (std::map<Expression*, Node*>::iterator p = Node::expressions.begin();
       p != Node::expressions.end();
       ++p)
    delete p->second;
  Node::expressions.clear();

  for (std::map<Statement*, Node*>::iterator p = Node::statements.begin();
       p != Node::statements.end();
       ++p)
    delete p->second;
  Node::statements.clear();

  for (std::vector<Node*>::iterator p = Node::indirects.begin();
       p != Node::indirects.end();
       ++p)
    delete *p;
  Node::indirects.clear();
}
