// 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;

  bool big = false;
  if (t->struct_type() != NULL
      || (t->array_type() != NULL && !t->is_slice_type()))
    {
      int64_t size;
      bool ok = t->backend_type_size(context->gogo(), &size);
      big = ok && (size < 0 || size > 10 * 1024 * 1024);
    }

  if (this->expr() != NULL)
    {
      if (this->expr()->allocation_expression() != NULL)
	{
	  Type* pt = t->deref();
	  if (pt->struct_type() != NULL
	      || (pt->array_type() != NULL && !pt->is_slice_type()))
	    {
	      int64_t size;
	      bool ok = pt->backend_type_size(context->gogo(), &size);
	      if (ok)
		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;
}

Unordered_map(Named_object*, Node*) Node::objects;
Unordered_map(Expression*, Node*) Node::expressions;
Unordered_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)
{
  std::pair<Named_object*, Node*> val(no, NULL);
  std::pair<Unordered_map(Named_object*, Node*)::iterator, bool> ins =
    Node::objects.insert(val);
  if (ins.second)
    ins.first->second = new Node(no);
  return ins.first->second;
}

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

Node*
Node::make_node(Expression* e)
{
  std::pair<Expression*, Node*> val(e, NULL);
  std::pair<Unordered_map(Expression*, Node*)::iterator, bool> ins =
    Node::expressions.insert(val);
  if (ins.second)
    ins.first->second = new Node(e);
  return ins.first->second;
}

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

Node*
Node::make_node(Statement* s)
{
  std::pair<Statement*, Node*> val(s, NULL);
  std::pair<Unordered_map(Statement*, Node*)::iterator, bool> ins =
    Node::statements.insert(val);
  if (ins.second)
    ins.first->second = new Node(s);
  return ins.first->second;
}

// 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_debug((*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_debug((*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_debug(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_debug(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_debug((*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)
    {
      std::string fn_name = this->context_->current_function_name();
      go_debug((*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_debug((*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::MAPASSIGN_FAST32PTR:
              case Runtime::MAPASSIGN_FAST64PTR:
              case Runtime::MAPASSIGN_FASTSTR:
                {
                  // Map key escapes. The last argument is the key.
                  Node* key_node = Node::make_node(call->args()->back());
                  this->assign(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_UNSAFE_CONVERSION:
      {
        Unsafe_type_conversion_expression* uce =
          (*pexpr)->unsafe_conversion_expression();
        Node* expr_node = Node::make_node(uce->expr());
        this->assign(n, expr_node);
      }
      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_SLICE_VALUE:
      {
	// Connect the pointer field to the slice value.
	Node* slice_node = Node::make_node(*pexpr);
	Node* ptr_node =
	  Node::make_node((*pexpr)->slice_value_expression()->valmem());
	this->assign(slice_node, ptr_node);
      }
      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);
            if (array_state->loop_depth != 0)
              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_debug(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_debug(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_debug(call->location(), "esccall:: ... <- %s, untracked",
			 (*p)->ast_format(gogo).c_str());
	      this->assign(this->context_->sink(), *p);
	    }
	}

      return;
    }

  if (debug_level > 2)
    go_debug(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(), Type::COMPARE_TAGS,
				   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(),
				   Type::COMPARE_TAGS, 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_debug(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_debug(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_SLICE_VALUE:
	  // DST = slice{ptr, len, cap}
	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())
                || tt->interface_type() != NULL)
              {
                // string([]byte), string([]rune), []byte(string), []rune(string), string(rune),
                // interface(T)
                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_debug(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_debug(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;

      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_debug(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_debug(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_debug(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_debug(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_debug(src->definition_location(), "leaking param content: %s",
		     src->ast_format(gogo).c_str());
	}
      else
	{
	  if (debug_level != 0)
	    go_debug(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_debug(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_debug(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_debug(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_debug(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_debug(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_debug(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_debug(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_debug(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())
              || tt->interface_type() != NULL)
            {
              // string([]byte), string([]rune), []byte(string), []rune(string), string(rune),
              // interface(T)
              src->set_encoding(Node::ESCAPE_HEAP);
              if (debug_level != 0 && osrcesc != src->encoding())
                go_debug(src->location(), "%s escapes to heap",
			 src->ast_format(gogo).c_str());
              extra_loop_depth = mod_loop_depth;
              if (tt->interface_type() != NULL
                  && ft->has_pointer()
                  && !ft->is_direct_iface_type())
                // We're converting from a non-direct interface type.
                // The interface will hold a heap copy of the data
                // Flow the data to heap. See issue 29353.
                this->flood(level, this->context_->sink(),
                            Node::make_node(tce->expr()), -1);
            }
        }
      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_debug(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->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 (Unordered_map(Named_object*, Node*)::iterator p =
	 Node::objects.begin();
       p != Node::objects.end();
       ++p)
    delete p->second;
  Node::objects.clear();

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

  for (Unordered_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();
}
