// expressions.cc -- Go frontend expression handling.

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "go-system.h"

#include <algorithm>

#include "go-c.h"
#include "gogo.h"
#include "go-diagnostics.h"
#include "go-encode-id.h"
#include "types.h"
#include "export.h"
#include "import.h"
#include "statements.h"
#include "lex.h"
#include "runtime.h"
#include "backend.h"
#include "expressions.h"
#include "ast-dump.h"

// Class Expression.

Expression::Expression(Expression_classification classification,
		       Location location)
  : classification_(classification), location_(location)
{
}

Expression::~Expression()
{
}

// Traverse the expressions.

int
Expression::traverse(Expression** pexpr, Traverse* traverse)
{
  Expression* expr = *pexpr;
  if ((traverse->traverse_mask() & Traverse::traverse_expressions) != 0)
    {
      int t = traverse->expression(pexpr);
      if (t == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
      else if (t == TRAVERSE_SKIP_COMPONENTS)
	return TRAVERSE_CONTINUE;
    }
  return expr->do_traverse(traverse);
}

// Traverse subexpressions of this expression.

int
Expression::traverse_subexpressions(Traverse* traverse)
{
  return this->do_traverse(traverse);
}

// A traversal used to set the location of subexpressions.

class Set_location : public Traverse
{
 public:
  Set_location(Location loc)
    : Traverse(traverse_expressions),
      loc_(loc)
  { }

  int
  expression(Expression** pexpr);

 private:
  Location loc_;
};

// Set the location of an expression.

int
Set_location::expression(Expression** pexpr)
{
  // Some expressions are shared or don't have an independent
  // location, so we shouldn't change their location.  This is the set
  // of expressions for which do_copy is just "return this" or
  // otherwise does not pass down the location.
  switch ((*pexpr)->classification())
    {
    case Expression::EXPRESSION_ERROR:
    case Expression::EXPRESSION_VAR_REFERENCE:
    case Expression::EXPRESSION_ENCLOSED_VAR_REFERENCE:
    case Expression::EXPRESSION_STRING:
    case Expression::EXPRESSION_FUNC_DESCRIPTOR:
    case Expression::EXPRESSION_TYPE:
    case Expression::EXPRESSION_BOOLEAN:
    case Expression::EXPRESSION_CONST_REFERENCE:
    case Expression::EXPRESSION_NIL:
    case Expression::EXPRESSION_TYPE_DESCRIPTOR:
    case Expression::EXPRESSION_GC_SYMBOL:
    case Expression::EXPRESSION_PTRMASK_SYMBOL:
    case Expression::EXPRESSION_TYPE_INFO:
    case Expression::EXPRESSION_STRUCT_FIELD_OFFSET:
      return TRAVERSE_CONTINUE;
    default:
      break;
    }

  (*pexpr)->location_ = this->loc_;
  return TRAVERSE_CONTINUE;
}

// Set the location of an expression and its subexpressions.

void
Expression::set_location(Location loc)
{
  this->location_ = loc;
  Set_location sl(loc);
  this->traverse_subexpressions(&sl);
}

// Default implementation for do_traverse for child classes.

int
Expression::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// This virtual function is called by the parser if the value of this
// expression is being discarded.  By default, we give an error.
// Expressions with side effects override.

bool
Expression::do_discarding_value()
{
  this->unused_value_error();
  return false;
}

// This virtual function is called to export expressions.  This will
// only be used by expressions which may be constant.

void
Expression::do_export(Export_function_body*) const
{
  go_unreachable();
}

// Write a name to the export data.

void
Expression::export_name(Export_function_body* efb, const Named_object* no)
{
  if (no->package() != NULL)
    {
      char buf[50];
      snprintf(buf, sizeof buf, "<p%d>", efb->package_index(no->package()));
      efb->write_c_string(buf);
    }

  if (!Gogo::is_hidden_name(no->name()))
    efb->write_string(no->name());
  else
    {
      efb->write_c_string(".");
      efb->write_string(Gogo::unpack_hidden_name(no->name()));
    }
}

// Give an error saying that the value of the expression is not used.

void
Expression::unused_value_error()
{
  if (this->type()->is_error())
    {
      go_assert(saw_errors());
      this->set_is_error();
    }
  else
    this->report_error(_("value computed is not used"));
}

// Note that this expression is an error.  This is called by children
// when they discover an error.

void
Expression::set_is_error()
{
  this->classification_ = EXPRESSION_ERROR;
}

// For children to call to report an error conveniently.

void
Expression::report_error(const char* msg)
{
  go_error_at(this->location_, "%s", msg);
  this->set_is_error();
}

// Set types of variables and constants.  This is implemented by the
// child class.

void
Expression::determine_type(const Type_context* context)
{
  this->do_determine_type(context);
}

// Set types when there is no context.

void
Expression::determine_type_no_context()
{
  Type_context context;
  this->do_determine_type(&context);
}

// Return true if two expressions refer to the same variable or struct
// field.  This can only be true when there are no side effects.

bool
Expression::is_same_variable(Expression* a, Expression* b)
{
  if (a->classification() != b->classification())
    return false;

  Var_expression* av = a->var_expression();
  if (av != NULL)
    return av->named_object() == b->var_expression()->named_object();

  Field_reference_expression* af = a->field_reference_expression();
  if (af != NULL)
    {
      Field_reference_expression* bf = b->field_reference_expression();
      return (af->field_index() == bf->field_index()
	      && Expression::is_same_variable(af->expr(), bf->expr()));
    }

  Unary_expression* au = a->unary_expression();
  if (au != NULL)
    {
      Unary_expression* bu = b->unary_expression();
      return (au->op() == OPERATOR_MULT
	      && bu->op() == OPERATOR_MULT
	      && Expression::is_same_variable(au->operand(),
					      bu->operand()));
    }

  Array_index_expression* aie = a->array_index_expression();
  if (aie != NULL)
    {
      Array_index_expression* bie = b->array_index_expression();
      return (aie->end() == NULL
	      && bie->end() == NULL
	      && Expression::is_same_variable(aie->array(), bie->array())
	      && Expression::is_same_variable(aie->start(), bie->start()));
    }

  Numeric_constant aval;
  if (a->numeric_constant_value(&aval))
    {
      Numeric_constant bval;
      if (b->numeric_constant_value(&bval))
	return aval.equals(bval);
    }

  return false;
}

// Return an expression handling any conversions which must be done during
// assignment.

Expression*
Expression::convert_for_assignment(Gogo* gogo, Type* lhs_type,
				   Expression* rhs, Location location)
{
  Type* rhs_type = rhs->type();
  if (lhs_type->is_error()
      || rhs_type->is_error()
      || rhs->is_error_expression())
    return Expression::make_error(location);

  bool are_identical = Type::are_identical(lhs_type, rhs_type,
					   (Type::COMPARE_ERRORS
					    | Type::COMPARE_TAGS),
					   NULL);
  if (!are_identical && lhs_type->interface_type() != NULL)
    {
      // Type to interface conversions have been made explicit early.
      go_assert(rhs_type->interface_type() != NULL);
      return Expression::convert_interface_to_interface(lhs_type, rhs, false,
                                                        location);
    }
  else if (!are_identical && rhs_type->interface_type() != NULL)
    return Expression::convert_interface_to_type(gogo, lhs_type, rhs, location);
  else if (lhs_type->is_slice_type() && rhs_type->is_nil_type())
    {
      // Assigning nil to a slice.
      Expression* nil = Expression::make_nil(location);
      Expression* zero = Expression::make_integer_ul(0, NULL, location);
      return Expression::make_slice_value(lhs_type, nil, zero, zero, location);
    }
  else if (rhs_type->is_nil_type())
    return Expression::make_nil(location);
  else if (are_identical)
    {
      if (lhs_type->forwarded() != rhs_type->forwarded())
	{
	  // Different but identical types require an explicit
	  // conversion.  This happens with type aliases.
	  return Expression::make_cast(lhs_type, rhs, location);
	}

      // No conversion is needed.
      return rhs;
    }
  else if (lhs_type->points_to() != NULL)
    return Expression::make_unsafe_cast(lhs_type, rhs, location);
  else if (lhs_type->is_numeric_type())
    return Expression::make_cast(lhs_type, rhs, location);
  else if ((lhs_type->struct_type() != NULL
            && rhs_type->struct_type() != NULL)
           || (lhs_type->array_type() != NULL
               && rhs_type->array_type() != NULL))
    {
      // This conversion must be permitted by Go, or we wouldn't have
      // gotten here.
      return Expression::make_unsafe_cast(lhs_type, rhs, location);
    }
  else
    return rhs;
}

// Return an expression for a conversion from a non-interface type to an
// interface type.  If ON_STACK is true, it can allocate the storage on
// stack.

Expression*
Expression::convert_type_to_interface(Type* lhs_type, Expression* rhs,
                                      bool on_stack, Location location)
{
  Interface_type* lhs_interface_type = lhs_type->interface_type();
  bool lhs_is_empty = lhs_interface_type->is_empty();

  // Since RHS_TYPE is a static type, we can create the interface
  // method table at compile time.

  // When setting an interface to nil, we just set both fields to
  // NULL.
  Type* rhs_type = rhs->type();
  if (rhs_type->is_nil_type())
    {
      Expression* nil = Expression::make_nil(location);
      return Expression::make_interface_value(lhs_type, nil, nil, location);
    }

  // This should have been checked already.
  if (!lhs_interface_type->implements_interface(rhs_type, NULL))
    {
      go_assert(saw_errors());
      return Expression::make_error(location);
    }

  // An interface is a tuple.  If LHS_TYPE is an empty interface type,
  // then the first field is the type descriptor for RHS_TYPE.
  // Otherwise it is the interface method table for RHS_TYPE.
  Expression* first_field;
  if (lhs_is_empty)
    first_field = Expression::make_type_descriptor(rhs_type, location);
  else
    {
      // Build the interface method table for this interface and this
      // object type: a list of function pointers for each interface
      // method.
      Named_type* rhs_named_type = rhs_type->named_type();
      Struct_type* rhs_struct_type = rhs_type->struct_type();
      bool is_pointer = false;
      if (rhs_named_type == NULL && rhs_struct_type == NULL)
	{
	  rhs_named_type = rhs_type->deref()->named_type();
	  rhs_struct_type = rhs_type->deref()->struct_type();
	  is_pointer = true;
	}
      if (rhs_named_type != NULL)
	first_field =
	  rhs_named_type->interface_method_table(lhs_interface_type,
                                                 is_pointer);
      else if (rhs_struct_type != NULL)
	first_field =
	  rhs_struct_type->interface_method_table(lhs_interface_type,
                                                  is_pointer);
      else
	first_field = Expression::make_nil(location);
    }

  Expression* obj;
  if (rhs_type->is_direct_iface_type())
    {
      // We are assigning a pointer to the interface; the interface
      // holds the pointer itself.
      obj = unpack_direct_iface(rhs, location);
    }
  else
    {
      // We are assigning a non-pointer value to the interface; the
      // interface gets a copy of the value in the heap if it escapes.
      if (rhs->is_constant())
        obj = Expression::make_unary(OPERATOR_AND, rhs, location);
      else
        {
          obj = Expression::make_heap_expression(rhs, location);
          if (on_stack)
            obj->heap_expression()->set_allocate_on_stack();
        }
    }

  return Expression::make_interface_value(lhs_type, first_field, obj, location);
}

// Return an expression for the pointer-typed value of a direct interface
// type.  Specifically, for single field struct or array, get the single
// field, and do this recursively.  The reason for this is that we don't
// want to assign a struct or an array to a pointer-typed field.  The
// backend may not like that.

Expression*
Expression::unpack_direct_iface(Expression* rhs, Location loc)
{
  Struct_type* st = rhs->type()->struct_type();
  if (st != NULL)
    {
      go_assert(st->field_count() == 1);
      Expression* field = Expression::make_field_reference(rhs, 0, loc);
      return unpack_direct_iface(field, loc);
    }
  Array_type* at = rhs->type()->array_type();
  if (at != NULL)
    {
      int64_t len;
      bool ok = at->int_length(&len);
      go_assert(ok && len == 1);
      Type* int_type = Type::lookup_integer_type("int");
      Expression* index = Expression::make_integer_ul(0, int_type, loc);
      Expression* elem = Expression::make_array_index(rhs, index, NULL, NULL, loc);
      return unpack_direct_iface(elem, loc);
    }
  return rhs;
}

// The opposite of unpack_direct_iface.

Expression*
Expression::pack_direct_iface(Type* t, Expression* rhs, Location loc)
{
  if (rhs->type() == t)
    return rhs;
  Struct_type* st = t->struct_type();
  if (st != NULL)
    {
      Expression_list* vals = new Expression_list();
      vals->push_back(pack_direct_iface(st->field(0)->type(), rhs, loc));
      return Expression::make_struct_composite_literal(t, vals, loc);
    }
  Array_type* at = t->array_type();
  if (at != NULL)
    {
      Expression_list* vals = new Expression_list();
      vals->push_back(pack_direct_iface(at->element_type(), rhs, loc));
      return Expression::make_array_composite_literal(t, vals, loc);
    }
  return Expression::make_unsafe_cast(t, rhs, loc);
}

// Return an expression for the type descriptor of RHS.

Expression*
Expression::get_interface_type_descriptor(Expression* rhs)
{
  go_assert(rhs->type()->interface_type() != NULL);
  Location location = rhs->location();

  // The type descriptor is the first field of an empty interface.
  if (rhs->type()->interface_type()->is_empty())
    return Expression::make_interface_info(rhs, INTERFACE_INFO_TYPE_DESCRIPTOR,
                                           location);

  Expression* mtable =
      Expression::make_interface_info(rhs, INTERFACE_INFO_METHODS, location);

  Expression* descriptor =
      Expression::make_dereference(mtable, NIL_CHECK_NOT_NEEDED, location);
  descriptor = Expression::make_field_reference(descriptor, 0, location);
  Expression* nil = Expression::make_nil(location);

  Expression* eq =
      Expression::make_binary(OPERATOR_EQEQ, mtable, nil, location);
  return Expression::make_conditional(eq, nil, descriptor, location);
}

// Return an expression for the conversion of an interface type to an
// interface type.

Expression*
Expression::convert_interface_to_interface(Type *lhs_type, Expression* rhs,
                                           bool for_type_guard,
                                           Location location)
{
  if (Type::are_identical(lhs_type, rhs->type(),
			  Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			  NULL))
    return rhs;

  Interface_type* lhs_interface_type = lhs_type->interface_type();
  bool lhs_is_empty = lhs_interface_type->is_empty();

  // In the general case this requires runtime examination of the type
  // method table to match it up with the interface methods.

  // FIXME: If all of the methods in the right hand side interface
  // also appear in the left hand side interface, then we don't need
  // to do a runtime check, although we still need to build a new
  // method table.

  // We are going to evaluate RHS multiple times.
  go_assert(rhs->is_multi_eval_safe());

  // Get the type descriptor for the right hand side.  This will be
  // NULL for a nil interface.
  Expression* rhs_type_expr = Expression::get_interface_type_descriptor(rhs);
  Expression* lhs_type_expr =
      Expression::make_type_descriptor(lhs_type, location);

  Expression* first_field;
  if (for_type_guard)
    {
      // A type assertion fails when converting a nil interface.
      first_field = Runtime::make_call(Runtime::ASSERTITAB, location, 2,
				       lhs_type_expr, rhs_type_expr);
    }
  else if (lhs_is_empty)
    {
      // A conversion to an empty interface always succeeds, and the
      // first field is just the type descriptor of the object.
      first_field = rhs_type_expr;
    }
  else
    {
      // A conversion to a non-empty interface may fail, but unlike a
      // type assertion converting nil will always succeed.
      first_field = Runtime::make_call(Runtime::REQUIREITAB, location, 2,
				       lhs_type_expr, rhs_type_expr);
    }

  // The second field is simply the object pointer.
  Expression* obj =
      Expression::make_interface_info(rhs, INTERFACE_INFO_OBJECT, location);
  return Expression::make_interface_value(lhs_type, first_field, obj, location);
}

// Return an expression for the conversion of an interface type to a
// non-interface type.

Expression*
Expression::convert_interface_to_type(Gogo* gogo, Type *lhs_type, Expression* rhs,
                                      Location location)
{
  // We are going to evaluate RHS multiple times.
  go_assert(rhs->is_multi_eval_safe());

  // Build an expression to check that the type is valid.  It will
  // panic with an appropriate runtime type error if the type is not
  // valid.
  // (lhs_type == rhs_type ? nil /*dummy*/ :
  //    panicdottype(lhs_type, rhs_type, inter_type))
  // For some Oses, we need to call runtime.eqtype instead of
  // lhs_type == rhs_type, as we may have unmerged type descriptors
  // from shared libraries.
  Expression* lhs_type_expr = Expression::make_type_descriptor(lhs_type,
                                                                location);
  Expression* rhs_descriptor =
      Expression::get_interface_type_descriptor(rhs);

  Type* rhs_type = rhs->type();
  Expression* rhs_inter_expr = Expression::make_type_descriptor(rhs_type,
                                                                location);

  Expression* cond;
  if (gogo->need_eqtype()) {
    cond = Runtime::make_call(Runtime::EQTYPE, location,
                              2, lhs_type_expr,
                              rhs_descriptor);
  } else {
    cond = Expression::make_binary(OPERATOR_EQEQ, lhs_type_expr,
                                   rhs_descriptor, location);
  }

  rhs_descriptor = Expression::get_interface_type_descriptor(rhs);
  Expression* panic = Runtime::make_call(Runtime::PANICDOTTYPE, location,
                                         3, lhs_type_expr->copy(),
                                         rhs_descriptor,
                                         rhs_inter_expr);
  Expression* nil = Expression::make_nil(location);
  Expression* check = Expression::make_conditional(cond, nil, panic,
                                                   location);

  // If the conversion succeeds, pull out the value.
  Expression* obj = Expression::make_interface_info(rhs, INTERFACE_INFO_OBJECT,
                                                    location);

  // If the value is a direct interface, then it is the value we want.
  // Otherwise it points to the value.
  if (lhs_type->is_direct_iface_type())
    obj = Expression::pack_direct_iface(lhs_type, obj, location);
  else
    {
      obj = Expression::make_unsafe_cast(Type::make_pointer_type(lhs_type), obj,
                                         location);
      obj = Expression::make_dereference(obj, NIL_CHECK_NOT_NEEDED,
                                         location);
    }
  return Expression::make_compound(check, obj, location);
}

// Convert an expression to its backend representation.  This is implemented by
// the child class.  Not that it is not in general safe to call this multiple
// times for a single expression, but that we don't catch such errors.

Bexpression*
Expression::get_backend(Translate_context* context)
{
  // The child may have marked this expression as having an error.
  if (this->classification_ == EXPRESSION_ERROR)
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  return this->do_get_backend(context);
}

// Return a backend expression for VAL.
Bexpression*
Expression::backend_numeric_constant_expression(Translate_context* context,
                                                Numeric_constant* val)
{
  Gogo* gogo = context->gogo();
  Type* type = val->type();
  if (type == NULL)
    return gogo->backend()->error_expression();

  Btype* btype = type->get_backend(gogo);
  Bexpression* ret;
  if (type->integer_type() != NULL)
    {
      mpz_t ival;
      if (!val->to_int(&ival))
        {
          go_assert(saw_errors());
          return gogo->backend()->error_expression();
        }
      ret = gogo->backend()->integer_constant_expression(btype, ival);
      mpz_clear(ival);
    }
  else if (type->float_type() != NULL)
    {
      mpfr_t fval;
      if (!val->to_float(&fval))
        {
          go_assert(saw_errors());
          return gogo->backend()->error_expression();
        }
      ret = gogo->backend()->float_constant_expression(btype, fval);
      mpfr_clear(fval);
    }
  else if (type->complex_type() != NULL)
    {
      mpc_t cval;
      if (!val->to_complex(&cval))
        {
          go_assert(saw_errors());
          return gogo->backend()->error_expression();
        }
      ret = gogo->backend()->complex_constant_expression(btype, cval);
      mpc_clear(cval);
    }
  else
    go_unreachable();

  return ret;
}

// Insert bounds checks for an index expression.  Check that that VAL
// >= 0 and that it fits in an int.  Then check that VAL OP BOUND is
// true.  If any condition is false, call one of the CODE runtime
// functions, which will panic.

void
Expression::check_bounds(Expression* val, Operator op, Expression* bound,
			 Runtime::Function code,
			 Runtime::Function code_u,
			 Runtime::Function code_extend,
			 Runtime::Function code_extend_u,
			 Statement_inserter* inserter,
			 Location loc)
{
  go_assert(val->is_multi_eval_safe());
  go_assert(bound->is_multi_eval_safe());

  Type* int_type = Type::lookup_integer_type("int");
  int int_type_size = int_type->integer_type()->bits();

  Type* val_type = val->type();
  if (val_type->integer_type() == NULL)
    {
      go_assert(saw_errors());
      return;
    }
  int val_type_size = val_type->integer_type()->bits();
  bool val_is_unsigned = val_type->integer_type()->is_unsigned();

  // Check that VAL >= 0.
  Expression* check = NULL;
  if (!val_is_unsigned)
    {
      Expression* zero = Expression::make_integer_ul(0, val_type, loc);
      check = Expression::make_binary(OPERATOR_GE, val->copy(), zero, loc);
    }

  // If VAL's type is larger than int, check that VAL fits in an int.
  if (val_type_size > int_type_size
      || (val_type_size == int_type_size
	  && val_is_unsigned))
    {
      mpz_t one;
      mpz_init_set_ui(one, 1UL);

      // maxval = 2^(int_type_size - 1) - 1
      mpz_t maxval;
      mpz_init(maxval);
      mpz_mul_2exp(maxval, one, int_type_size - 1);
      mpz_sub_ui(maxval, maxval, 1);
      Expression* max = Expression::make_integer_z(&maxval, val_type, loc);
      mpz_clear(one);
      mpz_clear(maxval);

      Expression* cmp = Expression::make_binary(OPERATOR_LE, val->copy(),
						max, loc);
      if (check == NULL)
	check = cmp;
      else
	check = Expression::make_binary(OPERATOR_ANDAND, check, cmp, loc);
    }

  // For the final check we can assume that VAL fits in an int.
  Expression* ival;
  if (val_type == int_type)
    ival = val->copy();
  else
    ival = Expression::make_cast(int_type, val->copy(), loc);

  // BOUND is assumed to fit in an int.  Either it comes from len or
  // cap, or it was checked by an earlier call.
  Expression* ibound;
  if (bound->type() == int_type)
    ibound = bound->copy();
  else
    ibound = Expression::make_cast(int_type, bound->copy(), loc);

  Expression* cmp = Expression::make_binary(op, ival, ibound, loc);
  if (check == NULL)
    check = cmp;
  else
    check = Expression::make_binary(OPERATOR_ANDAND, check, cmp, loc);

  Runtime::Function c;
  if (val_type_size > int_type_size)
    {
      if (val_is_unsigned)
	c = code_extend_u;
      else
	c = code_extend;
    }
  else
    {
      if (val_is_unsigned)
	c = code_u;
      else
	c = code;
    }

  Expression* ignore = Expression::make_boolean(true, loc);
  Expression* crash = Runtime::make_call(c, loc, 2,
					 val->copy(), bound->copy());
  Expression* cond = Expression::make_conditional(check, ignore, crash, loc);
  inserter->insert(Statement::make_statement(cond, true));
}

void
Expression::dump_expression(Ast_dump_context* ast_dump_context) const
{
  this->do_dump_expression(ast_dump_context);
}

// Error expressions.  This are used to avoid cascading errors.

class Error_expression : public Expression
{
 public:
  Error_expression(Location location)
    : Expression(EXPRESSION_ERROR, location)
  { }

 protected:
  bool
  do_is_constant() const
  { return true; }

  bool
  do_numeric_constant_value(Numeric_constant* nc) const
  {
    nc->set_unsigned_long(NULL, 0);
    return true;
  }

  bool
  do_discarding_value()
  { return true; }

  Type*
  do_type()
  { return Type::make_error_type(); }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return this; }

  bool
  do_is_addressable() const
  { return true; }

  Bexpression*
  do_get_backend(Translate_context* context)
  { return context->backend()->error_expression(); }

  void
  do_dump_expression(Ast_dump_context*) const;
};

// Dump the ast representation for an error expression to a dump context.

void
Error_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "_Error_" ;
}

Expression*
Expression::make_error(Location location)
{
  return new Error_expression(location);
}

// An expression which is really a type.  This is used during parsing.
// It is an error if these survive after lowering.

class
Type_expression : public Expression
{
 public:
  Type_expression(Type* type, Location location)
    : Expression(EXPRESSION_TYPE, location),
      type_(type)
  { }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Type::traverse(this->type_, traverse); }

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*)
  { }

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void do_dump_expression(Ast_dump_context*) const;

 private:
  // The type which we are representing as an expression.
  Type* type_;
};

void
Type_expression::do_check_types(Gogo*)
{
  if (this->type_->is_error())
    {
      go_assert(saw_errors());
      this->set_is_error();
    }
  else
    this->report_error(_("invalid use of type"));
}

void
Type_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->dump_type(this->type_);
}

Expression*
Expression::make_type(Type* type, Location location)
{
  return new Type_expression(type, location);
}

// Class Parser_expression.

Type*
Parser_expression::do_type()
{
  // We should never really ask for the type of a Parser_expression.
  // However, it can happen, at least when we have an invalid const
  // whose initializer refers to the const itself.  In that case we
  // may ask for the type when lowering the const itself.
  go_assert(saw_errors());
  return Type::make_error_type();
}

// Class Var_expression.

// Lower a variable expression.  Here we just make sure that the
// initialization expression of the variable has been lowered.  This
// ensures that we will be able to determine the type of the variable
// if necessary.

Expression*
Var_expression::do_lower(Gogo* gogo, Named_object* function,
			 Statement_inserter* inserter, int)
{
  if (this->variable_->is_variable())
    {
      Variable* var = this->variable_->var_value();
      // This is either a local variable or a global variable.  A
      // reference to a variable which is local to an enclosing
      // function will be a reference to a field in a closure.
      if (var->is_global())
	{
	  function = NULL;
	  inserter = NULL;
	}
      var->lower_init_expression(gogo, function, inserter);
    }
  return this;
}

// Return the type of a reference to a variable.

Type*
Var_expression::do_type()
{
  if (this->variable_->is_variable())
    return this->variable_->var_value()->type();
  else if (this->variable_->is_result_variable())
    return this->variable_->result_var_value()->type();
  else
    go_unreachable();
}

// Determine the type of a reference to a variable.

void
Var_expression::do_determine_type(const Type_context*)
{
  if (this->variable_->is_variable())
    this->variable_->var_value()->determine_type();
}

// Something takes the address of this variable.  This means that we
// may want to move the variable onto the heap.

void
Var_expression::do_address_taken(bool escapes)
{
  if (!escapes)
    {
      if (this->variable_->is_variable())
	this->variable_->var_value()->set_non_escaping_address_taken();
      else if (this->variable_->is_result_variable())
	this->variable_->result_var_value()->set_non_escaping_address_taken();
      else
	go_unreachable();
    }
  else
    {
      if (this->variable_->is_variable())
	this->variable_->var_value()->set_address_taken();
      else if (this->variable_->is_result_variable())
	this->variable_->result_var_value()->set_address_taken();
      else
	go_unreachable();
    }

  if (this->variable_->is_variable()
      && this->variable_->var_value()->is_in_heap())
    {
      Node::make_node(this)->set_encoding(Node::ESCAPE_HEAP);
      Node::make_node(this->variable_)->set_encoding(Node::ESCAPE_HEAP);
    }
}

// Export a reference to a variable.

void
Var_expression::do_export(Export_function_body* efb) const
{
  Named_object* no = this->variable_;
  if (no->is_result_variable() || !no->var_value()->is_global())
    efb->write_string(Gogo::unpack_hidden_name(no->name()));
  else
    Expression::export_name(efb, no);
}

// Get the backend representation for a reference to a variable.

Bexpression*
Var_expression::do_get_backend(Translate_context* context)
{
  Bvariable* bvar = this->variable_->get_backend_variable(context->gogo(),
							  context->function());
  bool is_in_heap;
  Location loc = this->location();
  Btype* btype;
  Gogo* gogo = context->gogo();
  if (this->variable_->is_variable())
    {
      is_in_heap = this->variable_->var_value()->is_in_heap();
      btype = this->variable_->var_value()->type()->get_backend(gogo);
    }
  else if (this->variable_->is_result_variable())
    {
      is_in_heap = this->variable_->result_var_value()->is_in_heap();
      btype = this->variable_->result_var_value()->type()->get_backend(gogo);
    }
  else
    go_unreachable();

  Bexpression* ret =
      context->backend()->var_expression(bvar, loc);
  if (is_in_heap)
    ret = context->backend()->indirect_expression(btype, ret, true, loc);
  return ret;
}

// Ast dump for variable expression.

void
Var_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << this->variable_->message_name() ;
}

// Make a reference to a variable in an expression.

Expression*
Expression::make_var_reference(Named_object* var, Location location)
{
  if (var->is_sink())
    return Expression::make_sink(location);

  // FIXME: Creating a new object for each reference to a variable is
  // wasteful.
  return new Var_expression(var, location);
}

// Class Enclosed_var_expression.

int
Enclosed_var_expression::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// Lower the reference to the enclosed variable.

Expression*
Enclosed_var_expression::do_lower(Gogo* gogo, Named_object* function,
				  Statement_inserter* inserter, int)
{
  gogo->lower_expression(function, inserter, &this->reference_);
  return this;
}

// Flatten the reference to the enclosed variable.

Expression*
Enclosed_var_expression::do_flatten(Gogo* gogo, Named_object* function,
				    Statement_inserter* inserter)
{
  gogo->flatten_expression(function, inserter, &this->reference_);
  return this;
}

void
Enclosed_var_expression::do_address_taken(bool escapes)
{
  if (!escapes)
    {
      if (this->variable_->is_variable())
	this->variable_->var_value()->set_non_escaping_address_taken();
      else if (this->variable_->is_result_variable())
	this->variable_->result_var_value()->set_non_escaping_address_taken();
      else
	go_unreachable();
    }
  else
    {
      if (this->variable_->is_variable())
	this->variable_->var_value()->set_address_taken();
      else if (this->variable_->is_result_variable())
	this->variable_->result_var_value()->set_address_taken();
      else
	go_unreachable();
    }

  if (this->variable_->is_variable()
      && this->variable_->var_value()->is_in_heap())
    Node::make_node(this->variable_)->set_encoding(Node::ESCAPE_HEAP);
}

// Ast dump for enclosed variable expression.

void
Enclosed_var_expression::do_dump_expression(Ast_dump_context* adc) const
{
  adc->ostream() << this->variable_->message_name();
}

// Make a reference to a variable within an enclosing function.

Expression*
Expression::make_enclosing_var_reference(Expression* reference,
					 Named_object* var, Location location)
{
  return new Enclosed_var_expression(reference, var, location);
}

// Class Temporary_reference_expression.

// The type.

Type*
Temporary_reference_expression::do_type()
{
  return this->statement_->type();
}

// Called if something takes the address of this temporary variable.
// We never have to move temporary variables to the heap, but we do
// need to know that they must live in the stack rather than in a
// register.

void
Temporary_reference_expression::do_address_taken(bool)
{
  this->statement_->set_is_address_taken();
}

// Export a reference to a temporary.

void
Temporary_reference_expression::do_export(Export_function_body* efb) const
{
  unsigned int idx = efb->temporary_index(this->statement_);
  char buf[50];
  snprintf(buf, sizeof buf, "$t%u", idx);
  efb->write_c_string(buf);
}

// Import a reference to a temporary.

Expression*
Temporary_reference_expression::do_import(Import_function_body* ifb,
					  Location loc)
{
  std::string id = ifb->read_identifier();
  go_assert(id[0] == '$' && id[1] == 't');
  const char *p = id.c_str();
  char *end;
  long idx = strtol(p + 2, &end, 10);
  if (*end != '\0' || idx > 0x7fffffff)
    {
      if (!ifb->saw_error())
	go_error_at(loc,
		    ("invalid export data for %qs: "
		     "invalid temporary reference index at %lu"),
		    ifb->name().c_str(),
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return Expression::make_error(loc);
    }

  Temporary_statement* temp =
    ifb->temporary_statement(static_cast<unsigned int>(idx));
  if (temp == NULL)
    {
      if (!ifb->saw_error())
	go_error_at(loc,
		    ("invalid export data for %qs: "
		     "undefined temporary reference index at %lu"),
		    ifb->name().c_str(),
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return Expression::make_error(loc);
    }

  return Expression::make_temporary_reference(temp, loc);
}

// Get a backend expression referring to the variable.

Bexpression*
Temporary_reference_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Bvariable* bvar = this->statement_->get_backend_variable(context);
  Bexpression* ret = gogo->backend()->var_expression(bvar, this->location());

  // The backend can't always represent the same set of recursive types
  // that the Go frontend can.  In some cases this means that a
  // temporary variable won't have the right backend type.  Correct
  // that here by adding a type cast.  We need to use base() to push
  // the circularity down one level.
  Type* stype = this->statement_->type();
  if (!this->is_lvalue_
      && stype->points_to() != NULL
      && stype->points_to()->is_void_type())
    {
      Btype* btype = this->type()->base()->get_backend(gogo);
      ret = gogo->backend()->convert_expression(btype, ret, this->location());
    }
  return ret;
}

// Ast dump for temporary reference.

void
Temporary_reference_expression::do_dump_expression(
                                Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->dump_temp_variable_name(this->statement_);
}

// Make a reference to a temporary variable.

Temporary_reference_expression*
Expression::make_temporary_reference(Temporary_statement* statement,
				     Location location)
{
  statement->add_use();
  return new Temporary_reference_expression(statement, location);
}

// Class Set_and_use_temporary_expression.

// Return the type.

Type*
Set_and_use_temporary_expression::do_type()
{
  return this->statement_->type();
}

// Determine the type of the expression.

void
Set_and_use_temporary_expression::do_determine_type(
    const Type_context* context)
{
  this->expr_->determine_type(context);
}

// Take the address.

void
Set_and_use_temporary_expression::do_address_taken(bool)
{
  this->statement_->set_is_address_taken();
}

// Return the backend representation.

Bexpression*
Set_and_use_temporary_expression::do_get_backend(Translate_context* context)
{
  Location loc = this->location();
  Gogo* gogo = context->gogo();
  Bvariable* bvar = this->statement_->get_backend_variable(context);
  Bexpression* lvar_ref = gogo->backend()->var_expression(bvar, loc);

  Named_object* fn = context->function();
  go_assert(fn != NULL);
  Bfunction* bfn = fn->func_value()->get_or_make_decl(gogo, fn);
  Bexpression* bexpr = this->expr_->get_backend(context);
  Bstatement* set = gogo->backend()->assignment_statement(bfn, lvar_ref,
                                                          bexpr, loc);
  Bexpression* var_ref = gogo->backend()->var_expression(bvar, loc);
  Bexpression* ret = gogo->backend()->compound_expression(set, var_ref, loc);
  return ret;
}

// Dump.

void
Set_and_use_temporary_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << '(';
  ast_dump_context->dump_temp_variable_name(this->statement_);
  ast_dump_context->ostream() << " = ";
  this->expr_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ')';
}

// Make a set-and-use temporary.

Set_and_use_temporary_expression*
Expression::make_set_and_use_temporary(Temporary_statement* statement,
				       Expression* expr, Location location)
{
  return new Set_and_use_temporary_expression(statement, expr, location);
}

// A sink expression--a use of the blank identifier _.

class Sink_expression : public Expression
{
 public:
  Sink_expression(Location location)
    : Expression(EXPRESSION_SINK, location),
      type_(NULL), bvar_(NULL)
  { }

 protected:
  bool
  do_discarding_value()
  { return true; }

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  Expression*
  do_copy()
  { return new Sink_expression(this->location()); }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type of this sink variable.
  Type* type_;
  // The temporary variable we generate.
  Bvariable* bvar_;
};

// Return the type of a sink expression.

Type*
Sink_expression::do_type()
{
  if (this->type_ == NULL)
    return Type::make_sink_type();
  return this->type_;
}

// Determine the type of a sink expression.

void
Sink_expression::do_determine_type(const Type_context* context)
{
  if (context->type != NULL)
    this->type_ = context->type;
}

// Return a temporary variable for a sink expression.  This will
// presumably be a write-only variable which the middle-end will drop.

Bexpression*
Sink_expression::do_get_backend(Translate_context* context)
{
  Location loc = this->location();
  Gogo* gogo = context->gogo();
  if (this->bvar_ == NULL)
    {
      go_assert(this->type_ != NULL && !this->type_->is_sink_type());
      Named_object* fn = context->function();
      go_assert(fn != NULL);
      Bfunction* fn_ctx = fn->func_value()->get_or_make_decl(gogo, fn);
      Btype* bt = this->type_->get_backend(context->gogo());
      Bstatement* decl;
      this->bvar_ =
	gogo->backend()->temporary_variable(fn_ctx, context->bblock(), bt, NULL,
					    0, loc, &decl);
      Bexpression* var_ref =
          gogo->backend()->var_expression(this->bvar_, loc);
      var_ref = gogo->backend()->compound_expression(decl, var_ref, loc);
      return var_ref;
    }
  return gogo->backend()->var_expression(this->bvar_, loc);
}

// Ast dump for sink expression.

void
Sink_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "_" ;
}

// Make a sink expression.

Expression*
Expression::make_sink(Location location)
{
  return new Sink_expression(location);
}

// Class Func_expression.

// FIXME: Can a function expression appear in a constant expression?
// The value is unchanging.  Initializing a constant to the address of
// a function seems like it could work, though there might be little
// point to it.

// Traversal.

int
Func_expression::do_traverse(Traverse* traverse)
{
  return (this->closure_ == NULL
	  ? TRAVERSE_CONTINUE
	  : Expression::traverse(&this->closure_, traverse));
}

// Return the type of a function expression.

Type*
Func_expression::do_type()
{
  if (this->function_->is_function())
    return this->function_->func_value()->type();
  else if (this->function_->is_function_declaration())
    return this->function_->func_declaration_value()->type();
  else
    go_unreachable();
}

// Get the backend representation for the code of a function expression.

Bexpression*
Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
{
  Function_type* fntype;
  if (no->is_function())
    fntype = no->func_value()->type();
  else if (no->is_function_declaration())
    fntype = no->func_declaration_value()->type();
  else
    go_unreachable();

  // Builtin functions are handled specially by Call_expression.  We
  // can't take their address.
  if (fntype->is_builtin())
    {
      go_error_at(loc,
		  ("invalid use of special built-in function %qs; "
		   "must be called"),
		  no->message_name().c_str());
      return gogo->backend()->error_expression();
    }

  Bfunction* fndecl;
  if (no->is_function())
    fndecl = no->func_value()->get_or_make_decl(gogo, no);
  else if (no->is_function_declaration())
    fndecl = no->func_declaration_value()->get_or_make_decl(gogo, no);
  else
    go_unreachable();

  return gogo->backend()->function_code_expression(fndecl, loc);
}

// Get the backend representation for a function expression.  This is used when
// we take the address of a function rather than simply calling it.  A func
// value is represented as a pointer to a block of memory.  The first
// word of that memory is a pointer to the function code.  The
// remaining parts of that memory are the addresses of variables that
// the function closes over.

Bexpression*
Func_expression::do_get_backend(Translate_context* context)
{
  // If there is no closure, just use the function descriptor.
  if (this->closure_ == NULL)
    {
      Gogo* gogo = context->gogo();
      Named_object* no = this->function_;
      Expression* descriptor;
      if (no->is_function())
	descriptor = no->func_value()->descriptor(gogo, no);
      else if (no->is_function_declaration())
	{
	  if (no->func_declaration_value()->type()->is_builtin())
	    {
	      go_error_at(this->location(),
			  ("invalid use of special built-in function %qs; "
			   "must be called"),
			  no->message_name().c_str());
	      return gogo->backend()->error_expression();
	    }
	  descriptor = no->func_declaration_value()->descriptor(gogo, no);
	}
      else
	go_unreachable();

      Bexpression* bdesc = descriptor->get_backend(context);
      return gogo->backend()->address_expression(bdesc, this->location());
    }

  go_assert(this->function_->func_value()->enclosing() != NULL);

  // If there is a closure, then the closure is itself the function
  // expression.  It is a pointer to a struct whose first field points
  // to the function code and whose remaining fields are the addresses
  // of the closed-over variables.
  Bexpression *bexpr = this->closure_->get_backend(context);

  // Introduce a backend type conversion, to account for any differences
  // between the argument type (function descriptor, struct with a
  // single field) and the closure (struct with multiple fields).
  Gogo* gogo = context->gogo();
  Btype *btype = this->type()->get_backend(gogo);
  return gogo->backend()->convert_expression(btype, bexpr, this->location());
}

// The cost of inlining a function reference.

int
Func_expression::do_inlining_cost() const
{
  // FIXME: We don't inline references to nested functions.
  if (this->closure_ != NULL)
    return 0x100000;
  if (this->function_->is_function()
      && this->function_->func_value()->enclosing() != NULL)
    return 0x100000;

  return 1;
}

// Export a reference to a function.

void
Func_expression::do_export(Export_function_body* efb) const
{
  Expression::export_name(efb, this->function_);
}

// Ast dump for function.

void
Func_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << this->function_->name();
  if (this->closure_ != NULL)
    {
      ast_dump_context->ostream() << " {closure =  ";
      this->closure_->dump_expression(ast_dump_context);
      ast_dump_context->ostream() << "}";
    }
}

// Make a reference to a function in an expression.

Expression*
Expression::make_func_reference(Named_object* function, Expression* closure,
				Location location)
{
  Func_expression* fe = new Func_expression(function, closure, location);

  // Detect references to builtin functions and set the runtime code if
  // appropriate.
  if (function->is_function_declaration())
    fe->set_runtime_code(Runtime::name_to_code(function->name()));
  return fe;
}

// Class Func_descriptor_expression.

// Constructor.

Func_descriptor_expression::Func_descriptor_expression(Named_object* fn)
  : Expression(EXPRESSION_FUNC_DESCRIPTOR, fn->location()),
    fn_(fn), dvar_(NULL)
{
  go_assert(!fn->is_function() || !fn->func_value()->needs_closure());
}

// Traversal.

int
Func_descriptor_expression::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// All function descriptors have the same type.

Type* Func_descriptor_expression::descriptor_type;

void
Func_descriptor_expression::make_func_descriptor_type()
{
  if (Func_descriptor_expression::descriptor_type != NULL)
    return;
  Type* uintptr_type = Type::lookup_integer_type("uintptr");
  Type* struct_type = Type::make_builtin_struct_type(1, "fn", uintptr_type);
  Func_descriptor_expression::descriptor_type =
    Type::make_builtin_named_type("functionDescriptor", struct_type);
}

Type*
Func_descriptor_expression::do_type()
{
  Func_descriptor_expression::make_func_descriptor_type();
  return Func_descriptor_expression::descriptor_type;
}

// The backend representation for a function descriptor.

Bexpression*
Func_descriptor_expression::do_get_backend(Translate_context* context)
{
  Named_object* no = this->fn_;
  Location loc = no->location();
  if (this->dvar_ != NULL)
    return context->backend()->var_expression(this->dvar_, loc);

  Gogo* gogo = context->gogo();
  Backend_name bname;
  gogo->function_descriptor_backend_name(no, &bname);
  bool is_descriptor = false;
  if (no->is_function_declaration()
      && !no->func_declaration_value()->asm_name().empty()
      && Linemap::is_predeclared_location(no->location()))
    is_descriptor = true;

  // The runtime package implements some functions defined in the
  // syscall package.  Let the syscall package define the descriptor
  // in this case.
  if (gogo->compiling_runtime()
      && gogo->package_name() == "runtime"
      && no->is_function()
      && !no->func_value()->asm_name().empty()
      && no->func_value()->asm_name().compare(0, 8, "syscall.") == 0)
    is_descriptor = true;

  Btype* btype = this->type()->get_backend(gogo);

  Bvariable* bvar;
  if (no->package() != NULL || is_descriptor)
    bvar =
      context->backend()->immutable_struct_reference(bname.name(),
						     bname.optional_asm_name(),
						     btype, loc);
  else
    {
      Location bloc = Linemap::predeclared_location();

      // The runtime package has hash/equality functions that are
      // referenced by type descriptors outside of the runtime, so the
      // function descriptors must be visible even though they are not
      // exported.
      bool is_exported_runtime = false;
      if (gogo->compiling_runtime()
	  && gogo->package_name() == "runtime"
	  && (no->name().find("hash") != std::string::npos
	      || no->name().find("equal") != std::string::npos))
	is_exported_runtime = true;

      bool is_hidden = ((no->is_function()
			 && no->func_value()->enclosing() != NULL)
			|| (Gogo::is_hidden_name(no->name())
			    && !is_exported_runtime)
			|| Gogo::is_thunk(no));

      if (no->is_function() && no->func_value()->is_referenced_by_inline())
	is_hidden = false;

      unsigned int flags = 0;
      if (is_hidden)
	flags |= Backend::variable_is_hidden;
      bvar = context->backend()->immutable_struct(bname.name(),
						  bname.optional_asm_name(),
						  flags, btype, bloc);
      Expression_list* vals = new Expression_list();
      vals->push_back(Expression::make_func_code_reference(this->fn_, bloc));
      Expression* init =
	Expression::make_struct_composite_literal(this->type(), vals, bloc);
      Translate_context bcontext(gogo, NULL, NULL, NULL);
      bcontext.set_is_const();
      Bexpression* binit = init->get_backend(&bcontext);
      context->backend()->immutable_struct_set_init(bvar, bname.name(),
						    flags, btype, bloc, binit);
    }

  this->dvar_ = bvar;
  return gogo->backend()->var_expression(bvar, loc);
}

// Print a function descriptor expression.

void
Func_descriptor_expression::do_dump_expression(Ast_dump_context* context) const
{
  context->ostream() << "[descriptor " << this->fn_->name() << "]";
}

// Make a function descriptor expression.

Func_descriptor_expression*
Expression::make_func_descriptor(Named_object* fn)
{
  return new Func_descriptor_expression(fn);
}

// Make the function descriptor type, so that it can be converted.

void
Expression::make_func_descriptor_type()
{
  Func_descriptor_expression::make_func_descriptor_type();
}

// A reference to just the code of a function.

class Func_code_reference_expression : public Expression
{
 public:
  Func_code_reference_expression(Named_object* function, Location location)
    : Expression(EXPRESSION_FUNC_CODE_REFERENCE, location),
      function_(function)
  { }

 protected:
  int
  do_traverse(Traverse*)
  { return TRAVERSE_CONTINUE; }

  bool
  do_is_static_initializer() const
  { return true; }

  Type*
  do_type()
  { return Type::make_pointer_type(Type::make_void_type()); }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  {
    return Expression::make_func_code_reference(this->function_,
						this->location());
  }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context* context) const
  { context->ostream() << "[raw " << this->function_->name() << "]" ; }

 private:
  // The function.
  Named_object* function_;
};

// Get the backend representation for a reference to function code.

Bexpression*
Func_code_reference_expression::do_get_backend(Translate_context* context)
{
  return Func_expression::get_code_pointer(context->gogo(), this->function_,
					   this->location());
}

// Make a reference to the code of a function.

Expression*
Expression::make_func_code_reference(Named_object* function, Location location)
{
  return new Func_code_reference_expression(function, location);
}

// Class Unknown_expression.

// Return the name of an unknown expression.

const std::string&
Unknown_expression::name() const
{
  return this->named_object_->name();
}

// Lower a reference to an unknown name.

Expression*
Unknown_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
{
  Location location = this->location();
  Named_object* no = this->named_object_;
  Named_object* real;
  if (!no->is_unknown())
    real = no;
  else
    {
      real = no->unknown_value()->real_named_object();
      if (real == NULL)
	{
	  if (!this->no_error_message_)
	    go_error_at(location, "reference to undefined name %qs",
			this->named_object_->message_name().c_str());
	  return Expression::make_error(location);
	}
    }
  switch (real->classification())
    {
    case Named_object::NAMED_OBJECT_CONST:
      return Expression::make_const_reference(real, location);
    case Named_object::NAMED_OBJECT_TYPE:
      return Expression::make_type(real->type_value(), location);
    case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
      if (!this->no_error_message_)
	go_error_at(location, "reference to undefined type %qs",
		    real->message_name().c_str());
      return Expression::make_error(location);
    case Named_object::NAMED_OBJECT_VAR:
      real->var_value()->set_is_used();
      return Expression::make_var_reference(real, location);
    case Named_object::NAMED_OBJECT_FUNC:
    case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
      return Expression::make_func_reference(real, NULL, location);
    case Named_object::NAMED_OBJECT_PACKAGE:
      if (!this->no_error_message_)
	go_error_at(location, "unexpected reference to package");
      return Expression::make_error(location);
    default:
      go_unreachable();
    }
}

// Dump the ast representation for an unknown expression to a dump context.

void
Unknown_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "_Unknown_(" << this->named_object_->name()
			      << ")";
}

// Make a reference to an unknown name.

Unknown_expression*
Expression::make_unknown_reference(Named_object* no, Location location)
{
  return new Unknown_expression(no, location);
}

// Start exporting a type conversion for a constant, if needed.  This
// returns whether we need to export a closing parenthesis.

bool
Expression::export_constant_type(Export_function_body* efb, Type* type)
{
  if (type == NULL
      || type->is_abstract()
      || type == efb->type_context())
    return false;
  efb->write_c_string("$convert(");
  efb->write_type(type);
  efb->write_c_string(", ");
  return true;
}

// Finish a type conversion for a constant.

void
Expression::finish_export_constant_type(Export_function_body* efb, bool needed)
{
  if (needed)
    efb->write_c_string(")");
}

// A boolean expression.

class Boolean_expression : public Expression
{
 public:
  Boolean_expression(bool val, Location location)
    : Expression(EXPRESSION_BOOLEAN, location),
      val_(val), type_(NULL)
  { }

  static Expression*
  do_import(Import_expression*, Location);

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_is_constant() const
  { return true; }

  bool
  do_is_zero_value() const
  { return this->val_ == false; }

  bool
  do_boolean_constant_value(bool* val) const
  {
    *val = this->val_;
    return true;
  }

  bool
  do_is_static_initializer() const
  { return true; }

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context* context)
  { return context->backend()->boolean_constant_expression(this->val_); }

  int
  do_inlining_cost() const
  { return 1; }

  void
  do_export(Export_function_body* efb) const;

  void
  do_dump_expression(Ast_dump_context* ast_dump_context) const
  { ast_dump_context->ostream() << (this->val_ ? "true" : "false"); }

 private:
  // The constant.
  bool val_;
  // The type as determined by context.
  Type* type_;
};

// Traverse a boolean expression.  We just need to traverse the type
// if there is one.

int
Boolean_expression::do_traverse(Traverse* traverse)
{
  if (this->type_ != NULL)
    return Type::traverse(this->type_, traverse);
  return TRAVERSE_CONTINUE;
}

// Get the type.

Type*
Boolean_expression::do_type()
{
  if (this->type_ == NULL)
    this->type_ = Type::make_boolean_type();
  return this->type_;
}

// Set the type from the context.

void
Boolean_expression::do_determine_type(const Type_context* context)
{
  if (this->type_ != NULL && !this->type_->is_abstract())
    ;
  else if (context->type != NULL && context->type->is_boolean_type())
    this->type_ = context->type;
  else if (!context->may_be_abstract)
    this->type_ = Type::lookup_bool_type();
}

// Export a boolean constant.

void
Boolean_expression::do_export(Export_function_body* efb) const
{
  bool exported_type = Expression::export_constant_type(efb, this->type_);
  efb->write_c_string(this->val_ ? "$true" : "$false");
  Expression::finish_export_constant_type(efb, exported_type);
}

// Import a boolean constant.

Expression*
Boolean_expression::do_import(Import_expression* imp, Location loc)
{
  if (imp->version() >= EXPORT_FORMAT_V3)
    imp->require_c_string("$");
  if (imp->peek_char() == 't')
    {
      imp->require_c_string("true");
      return Expression::make_boolean(true, loc);
    }
  else
    {
      imp->require_c_string("false");
      return Expression::make_boolean(false, loc);
    }
}

// Make a boolean expression.

Expression*
Expression::make_boolean(bool val, Location location)
{
  return new Boolean_expression(val, location);
}

// Class String_expression.

// Traverse a string expression.  We just need to traverse the type
// if there is one.

int
String_expression::do_traverse(Traverse* traverse)
{
  if (this->type_ != NULL)
    return Type::traverse(this->type_, traverse);
  return TRAVERSE_CONTINUE;
}

// Get the type.

Type*
String_expression::do_type()
{
  if (this->type_ == NULL)
    this->type_ = Type::make_string_type();
  return this->type_;
}

// Set the type from the context.

void
String_expression::do_determine_type(const Type_context* context)
{
  if (this->type_ != NULL && !this->type_->is_abstract())
    ;
  else if (context->type != NULL && context->type->is_string_type())
    this->type_ = context->type;
  else if (!context->may_be_abstract)
    this->type_ = Type::lookup_string_type();
}

// Build a string constant.

Bexpression*
String_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Btype* btype = Type::make_string_type()->get_backend(gogo);

  Location loc = this->location();
  std::vector<Bexpression*> init(2);
  Bexpression* str_cst =
      gogo->backend()->string_constant_expression(this->val_);
  init[0] = gogo->backend()->address_expression(str_cst, loc);

  Btype* int_btype = Type::lookup_integer_type("int")->get_backend(gogo);
  mpz_t lenval;
  mpz_init_set_ui(lenval, this->val_.length());
  init[1] = gogo->backend()->integer_constant_expression(int_btype, lenval);
  mpz_clear(lenval);

  return gogo->backend()->constructor_expression(btype, init, loc);
}

 // Write string literal to string dump.

void
String_expression::export_string(String_dump* exp,
				 const String_expression* str)
{
  std::string s;
  s.reserve(str->val_.length() * 4 + 2);
  s += '"';
  for (std::string::const_iterator p = str->val_.begin();
       p != str->val_.end();
       ++p)
    {
      if (*p == '\\' || *p == '"')
	{
	  s += '\\';
	  s += *p;
	}
      else if (*p >= 0x20 && *p < 0x7f)
	s += *p;
      else if (*p == '\n')
	s += "\\n";
      else if (*p == '\t')
	s += "\\t";
      else
	{
	  s += "\\x";
	  unsigned char c = *p;
	  unsigned int dig = c >> 4;
	  s += dig < 10 ? '0' + dig : 'A' + dig - 10;
	  dig = c & 0xf;
	  s += dig < 10 ? '0' + dig : 'A' + dig - 10;
	}
    }
  s += '"';
  exp->write_string(s);
}

// Export a string expression.

void
String_expression::do_export(Export_function_body* efb) const
{
  bool exported_type = Expression::export_constant_type(efb, this->type_);
  String_expression::export_string(efb, this);
  Expression::finish_export_constant_type(efb, exported_type);
}

// Import a string expression.

Expression*
String_expression::do_import(Import_expression* imp, Location loc)
{
  imp->require_c_string("\"");
  std::string val;
  while (true)
    {
      int c = imp->get_char();
      if (c == '"' || c == -1)
	break;
      if (c != '\\')
	val += static_cast<char>(c);
      else
	{
	  c = imp->get_char();
	  if (c == '\\' || c == '"')
	    val += static_cast<char>(c);
	  else if (c == 'n')
	    val += '\n';
	  else if (c == 't')
	    val += '\t';
	  else if (c == 'x')
	    {
	      c = imp->get_char();
	      unsigned int vh = c >= '0' && c <= '9' ? c - '0' : c - 'A' + 10;
	      c = imp->get_char();
	      unsigned int vl = c >= '0' && c <= '9' ? c - '0' : c - 'A' + 10;
	      char v = (vh << 4) | vl;
	      val += v;
	    }
	  else
	    {
	      go_error_at(imp->location(), "bad string constant");
	      return Expression::make_error(loc);
	    }
	}
    }
  return Expression::make_string(val, loc);
}

// Ast dump for string expression.

void
String_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  String_expression::export_string(ast_dump_context, this);
}

// Make a string expression with abstract string type (common case).

Expression*
Expression::make_string(const std::string& val, Location location)
{
  return new String_expression(val, NULL, location);
}

// Make a string expression with a specific string type.

Expression*
Expression::make_string_typed(const std::string& val, Type* type, Location location)
{
  return new String_expression(val, type, location);
}

// An expression that evaluates to some characteristic of a string.
// This is used when indexing, bound-checking, or nil checking a string.

class String_info_expression : public Expression
{
 public:
  String_info_expression(Expression* string, String_info string_info,
                        Location location)
    : Expression(EXPRESSION_STRING_INFO, location),
      string_(string), string_info_(string_info)
  { }

 protected:
  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { go_unreachable(); }

  Expression*
  do_copy()
  {
    return new String_info_expression(this->string_->copy(), this->string_info_,
				      this->location());
  }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

  void
  do_issue_nil_check()
  { this->string_->issue_nil_check(); }

 private:
  // The string for which we are getting information.
  Expression* string_;
  // What information we want.
  String_info string_info_;
};

// Return the type of the string info.

Type*
String_info_expression::do_type()
{
  switch (this->string_info_)
    {
    case STRING_INFO_DATA:
      {
	Type* byte_type = Type::lookup_integer_type("uint8");
	return Type::make_pointer_type(byte_type);
      }
    case STRING_INFO_LENGTH:
        return Type::lookup_integer_type("int");
    default:
      go_unreachable();
    }
}

// Return string information in GENERIC.

Bexpression*
String_info_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();

  Bexpression* bstring = this->string_->get_backend(context);
  switch (this->string_info_)
    {
    case STRING_INFO_DATA:
    case STRING_INFO_LENGTH:
      return gogo->backend()->struct_field_expression(bstring,
						      this->string_info_,
						      this->location());
      break;
    default:
      go_unreachable();
    }
}

// Dump ast representation for a type info expression.

void
String_info_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "stringinfo(";
  this->string_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ",";
  ast_dump_context->ostream() <<
      (this->string_info_ == STRING_INFO_DATA ? "data"
    : this->string_info_ == STRING_INFO_LENGTH ? "length"
    : "unknown");
  ast_dump_context->ostream() << ")";
}

// Make a string info expression.

Expression*
Expression::make_string_info(Expression* string, String_info string_info,
                            Location location)
{
  return new String_info_expression(string, string_info, location);
}

// An expression that represents an string value: a struct with value pointer
// and length fields.

class String_value_expression : public Expression
{
 public:
  String_value_expression(Expression* valptr, Expression* len, Location location)
      : Expression(EXPRESSION_STRING_VALUE, location),
        valptr_(valptr), len_(len)
  { }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type()
  { return Type::make_string_type(); }

  void
  do_determine_type(const Type_context*)
  { go_unreachable(); }

  Expression*
  do_copy()
  {
    return new String_value_expression(this->valptr_->copy(),
                                       this->len_->copy(),
                                       this->location());
  }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The value pointer.
  Expression* valptr_;
  // The length.
  Expression* len_;
};

int
String_value_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->valptr_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->len_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

Bexpression*
String_value_expression::do_get_backend(Translate_context* context)
{
  std::vector<Bexpression*> vals(2);
  vals[0] = this->valptr_->get_backend(context);
  vals[1] = this->len_->get_backend(context);

  Gogo* gogo = context->gogo();
  Btype* btype = Type::make_string_type()->get_backend(gogo);
  return gogo->backend()->constructor_expression(btype, vals, this->location());
}

void
String_value_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "stringvalue(";
  ast_dump_context->ostream() << "value: ";
  this->valptr_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ", length: ";
  this->len_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ")";
}

Expression*
Expression::make_string_value(Expression* valptr, Expression* len,
                              Location location)
{
  return new String_value_expression(valptr, len, location);
}

// Make an integer expression.

class Integer_expression : public Expression
{
 public:
  Integer_expression(const mpz_t* val, Type* type, bool is_character_constant,
		     Location location)
    : Expression(EXPRESSION_INTEGER, location),
      type_(type), is_character_constant_(is_character_constant)
  { mpz_init_set(this->val_, *val); }

  static Expression*
  do_import(Import_expression*, Location);

  // Write VAL to string dump.
  static void
  export_integer(String_dump* exp, const mpz_t val);

  // Write VAL to dump context.
  static void
  dump_integer(Ast_dump_context* ast_dump_context, const mpz_t val);

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_is_constant() const
  { return true; }

  bool
  do_is_zero_value() const
  { return mpz_sgn(this->val_) == 0; }

  bool
  do_is_static_initializer() const
  { return true; }

  bool
  do_numeric_constant_value(Numeric_constant* nc) const;

  Type*
  do_type();

  void
  do_determine_type(const Type_context* context);

  void
  do_check_types(Gogo*);

  Bexpression*
  do_get_backend(Translate_context*);

  Expression*
  do_copy()
  {
    if (this->is_character_constant_)
      return Expression::make_character(&this->val_,
					(this->type_ == NULL
					 ? NULL
					 : this->type_->copy_expressions()),
					this->location());
    else
      return Expression::make_integer_z(&this->val_,
					(this->type_ == NULL
					 ? NULL
					 : this->type_->copy_expressions()),
					this->location());
  }

  int
  do_inlining_cost() const
  { return 1; }

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The integer value.
  mpz_t val_;
  // The type so far.
  Type* type_;
  // Whether this is a character constant.
  bool is_character_constant_;
};

// Traverse an integer expression.  We just need to traverse the type
// if there is one.

int
Integer_expression::do_traverse(Traverse* traverse)
{
  if (this->type_ != NULL)
    return Type::traverse(this->type_, traverse);
  return TRAVERSE_CONTINUE;
}

// Return a numeric constant for this expression.  We have to mark
// this as a character when appropriate.

bool
Integer_expression::do_numeric_constant_value(Numeric_constant* nc) const
{
  if (this->is_character_constant_)
    nc->set_rune(this->type_, this->val_);
  else
    nc->set_int(this->type_, this->val_);
  return true;
}

// Return the current type.  If we haven't set the type yet, we return
// an abstract integer type.

Type*
Integer_expression::do_type()
{
  if (this->type_ == NULL)
    {
      if (this->is_character_constant_)
	this->type_ = Type::make_abstract_character_type();
      else
	this->type_ = Type::make_abstract_integer_type();
    }
  return this->type_;
}

// Set the type of the integer value.  Here we may switch from an
// abstract type to a real type.

void
Integer_expression::do_determine_type(const Type_context* context)
{
  if (this->type_ != NULL && !this->type_->is_abstract())
    ;
  else if (context->type != NULL && context->type->is_numeric_type())
    this->type_ = context->type;
  else if (!context->may_be_abstract)
    {
      if (this->is_character_constant_)
	this->type_ = Type::lookup_integer_type("int32");
      else
	this->type_ = Type::lookup_integer_type("int");
    }
}

// Check the type of an integer constant.

void
Integer_expression::do_check_types(Gogo*)
{
  Type* type = this->type_;
  if (type == NULL)
    return;
  Numeric_constant nc;
  if (this->is_character_constant_)
    nc.set_rune(NULL, this->val_);
  else
    nc.set_int(NULL, this->val_);
  if (!nc.set_type(type, true, this->location()))
    this->set_is_error();
}

// Get the backend representation for an integer constant.

Bexpression*
Integer_expression::do_get_backend(Translate_context* context)
{
  if (this->is_error_expression()
      || (this->type_ != NULL && this->type_->is_error_type()))
    {
      go_assert(saw_errors());
      return context->gogo()->backend()->error_expression();
    }

  Type* resolved_type = NULL;
  if (this->type_ != NULL && !this->type_->is_abstract())
    resolved_type = this->type_;
  else if (this->type_ != NULL && this->type_->float_type() != NULL)
    {
      // We are converting to an abstract floating point type.
      resolved_type = Type::lookup_float_type("float64");
    }
  else if (this->type_ != NULL && this->type_->complex_type() != NULL)
    {
      // We are converting to an abstract complex type.
      resolved_type = Type::lookup_complex_type("complex128");
    }
  else
    {
      // If we still have an abstract type here, then this is being
      // used in a constant expression which didn't get reduced for
      // some reason.  Use a type which will fit the value.  We use <,
      // not <=, because we need an extra bit for the sign bit.
      int bits = mpz_sizeinbase(this->val_, 2);
      Type* int_type = Type::lookup_integer_type("int");
      if (bits < int_type->integer_type()->bits())
	resolved_type = int_type;
      else if (bits < 64)
        resolved_type = Type::lookup_integer_type("int64");
      else
        {
          if (!saw_errors())
            go_error_at(this->location(),
                        "unknown type for large integer constant");
          return context->gogo()->backend()->error_expression();
        }
    }
  Numeric_constant nc;
  nc.set_int(resolved_type, this->val_);
  return Expression::backend_numeric_constant_expression(context, &nc);
}

// Write VAL to export data.

void
Integer_expression::export_integer(String_dump* exp, const mpz_t val)
{
  char* s = mpz_get_str(NULL, 10, val);
  exp->write_c_string(s);
  free(s);
}

// Export an integer in a constant expression.

void
Integer_expression::do_export(Export_function_body* efb) const
{
  bool exported_type = Expression::export_constant_type(efb, this->type_);

  Integer_expression::export_integer(efb, this->val_);
  if (this->is_character_constant_)
    efb->write_c_string("'");
  // A trailing space lets us reliably identify the end of the number.
  efb->write_c_string(" ");

  Expression::finish_export_constant_type(efb, exported_type);
}

// Import an integer, floating point, or complex value.  This handles
// all these types because they all start with digits.

Expression*
Integer_expression::do_import(Import_expression* imp, Location loc)
{
  std::string num = imp->read_identifier();
  imp->require_c_string(" ");
  if (!num.empty() && num[num.length() - 1] == 'i')
    {
      mpfr_t real;
      size_t plus_pos = num.find('+', 1);
      size_t minus_pos = num.find('-', 1);
      size_t pos;
      if (plus_pos == std::string::npos)
	pos = minus_pos;
      else if (minus_pos == std::string::npos)
	pos = plus_pos;
      else
	{
	  go_error_at(imp->location(), "bad number in import data: %qs",
		      num.c_str());
	  return Expression::make_error(loc);
	}
      if (pos == std::string::npos)
	mpfr_set_ui(real, 0, MPFR_RNDN);
      else
	{
	  std::string real_str = num.substr(0, pos);
	  if (mpfr_init_set_str(real, real_str.c_str(), 10, MPFR_RNDN) != 0)
	    {
	      go_error_at(imp->location(), "bad number in import data: %qs",
			  real_str.c_str());
	      return Expression::make_error(loc);
	    }
	}

      std::string imag_str;
      if (pos == std::string::npos)
	imag_str = num;
      else
	imag_str = num.substr(pos);
      imag_str = imag_str.substr(0, imag_str.size() - 1);
      mpfr_t imag;
      if (mpfr_init_set_str(imag, imag_str.c_str(), 10, MPFR_RNDN) != 0)
	{
	  go_error_at(imp->location(), "bad number in import data: %qs",
		      imag_str.c_str());
	  return Expression::make_error(loc);
	}
      mpc_t cval;
      mpc_init2(cval, mpc_precision);
      mpc_set_fr_fr(cval, real, imag, MPC_RNDNN);
      mpfr_clear(real);
      mpfr_clear(imag);
      Expression* ret = Expression::make_complex(&cval, NULL, loc);
      mpc_clear(cval);
      return ret;
    }
  else if (num.find('.') == std::string::npos
	   && num.find('E') == std::string::npos)
    {
      bool is_character_constant = (!num.empty()
				    && num[num.length() - 1] == '\'');
      if (is_character_constant)
	num = num.substr(0, num.length() - 1);
      mpz_t val;
      if (mpz_init_set_str(val, num.c_str(), 10) != 0)
	{
	  go_error_at(imp->location(), "bad number in import data: %qs",
		      num.c_str());
	  return Expression::make_error(loc);
	}
      Expression* ret;
      if (is_character_constant)
	ret = Expression::make_character(&val, NULL, loc);
      else
	ret = Expression::make_integer_z(&val, NULL, loc);
      mpz_clear(val);
      return ret;
    }
  else
    {
      mpfr_t val;
      if (mpfr_init_set_str(val, num.c_str(), 10, MPFR_RNDN) != 0)
	{
	  go_error_at(imp->location(), "bad number in import data: %qs",
		      num.c_str());
	  return Expression::make_error(loc);
	}
      Expression* ret = Expression::make_float(&val, NULL, loc);
      mpfr_clear(val);
      return ret;
    }
}
// Ast dump for integer expression.

void
Integer_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  if (this->is_character_constant_)
    ast_dump_context->ostream() << '\'';
  Integer_expression::export_integer(ast_dump_context, this->val_);
  if (this->is_character_constant_)
    ast_dump_context->ostream() << '\'';
}

// Build a new integer value from a multi-precision integer.

Expression*
Expression::make_integer_z(const mpz_t* val, Type* type, Location location)
{
  return new Integer_expression(val, type, false, location);
}

// Build a new integer value from an unsigned long.

Expression*
Expression::make_integer_ul(unsigned long val, Type *type, Location location)
{
  mpz_t zval;
  mpz_init_set_ui(zval, val);
  Expression* ret = Expression::make_integer_z(&zval, type, location);
  mpz_clear(zval);
  return ret;
}

// Build a new integer value from a signed long.

Expression*
Expression::make_integer_sl(long val, Type *type, Location location)
{
  mpz_t zval;
  mpz_init_set_si(zval, val);
  Expression* ret = Expression::make_integer_z(&zval, type, location);
  mpz_clear(zval);
  return ret;
}

// Store an int64_t in an uninitialized mpz_t.

static void
set_mpz_from_int64(mpz_t* zval, int64_t val)
{
  if (val >= 0)
    {
      unsigned long ul = static_cast<unsigned long>(val);
      if (static_cast<int64_t>(ul) == val)
	{
	  mpz_init_set_ui(*zval, ul);
	  return;
	}
    }
  uint64_t uv;
  if (val >= 0)
    uv = static_cast<uint64_t>(val);
  else
    uv = static_cast<uint64_t>(- val);
  unsigned long ul = uv & 0xffffffffUL;
  mpz_init_set_ui(*zval, ul);
  mpz_t hval;
  mpz_init_set_ui(hval, static_cast<unsigned long>(uv >> 32));
  mpz_mul_2exp(hval, hval, 32);
  mpz_add(*zval, *zval, hval);
  mpz_clear(hval);
  if (val < 0)
    mpz_neg(*zval, *zval);
}

// Build a new integer value from an int64_t.

Expression*
Expression::make_integer_int64(int64_t val, Type* type, Location location)
{
  mpz_t zval;
  set_mpz_from_int64(&zval, val);
  Expression* ret = Expression::make_integer_z(&zval, type, location);
  mpz_clear(zval);
  return ret;
}

// Build a new character constant value.

Expression*
Expression::make_character(const mpz_t* val, Type* type, Location location)
{
  return new Integer_expression(val, type, true, location);
}

// Floats.

class Float_expression : public Expression
{
 public:
  Float_expression(const mpfr_t* val, Type* type, Location location)
    : Expression(EXPRESSION_FLOAT, location),
      type_(type)
  {
    mpfr_init_set(this->val_, *val, MPFR_RNDN);
  }

  // Write VAL to export data.
  static void
  export_float(String_dump* exp, const mpfr_t val);

  // Write VAL to dump file.
  static void
  dump_float(Ast_dump_context* ast_dump_context, const mpfr_t val);

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_is_constant() const
  { return true; }

  bool
  do_is_zero_value() const
  {
    return mpfr_zero_p(this->val_) != 0
           && mpfr_signbit(this->val_) == 0;
  }

  bool
  do_is_static_initializer() const
  { return true; }

  bool
  do_numeric_constant_value(Numeric_constant* nc) const
  {
    nc->set_float(this->type_, this->val_);
    return true;
  }

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  { return Expression::make_float(&this->val_,
				  (this->type_ == NULL
				   ? NULL
				   : this->type_->copy_expressions()),
				  this->location()); }

  Bexpression*
  do_get_backend(Translate_context*);

  int
  do_inlining_cost() const
  { return 1; }

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The floating point value.
  mpfr_t val_;
  // The type so far.
  Type* type_;
};

// Traverse a float expression.  We just need to traverse the type if
// there is one.

int
Float_expression::do_traverse(Traverse* traverse)
{
  if (this->type_ != NULL)
    return Type::traverse(this->type_, traverse);
  return TRAVERSE_CONTINUE;
}

// Return the current type.  If we haven't set the type yet, we return
// an abstract float type.

Type*
Float_expression::do_type()
{
  if (this->type_ == NULL)
    this->type_ = Type::make_abstract_float_type();
  return this->type_;
}

// Set the type of the float value.  Here we may switch from an
// abstract type to a real type.

void
Float_expression::do_determine_type(const Type_context* context)
{
  if (this->type_ != NULL && !this->type_->is_abstract())
    ;
  else if (context->type != NULL
	   && (context->type->integer_type() != NULL
	       || context->type->float_type() != NULL
	       || context->type->complex_type() != NULL))
    this->type_ = context->type;
  else if (!context->may_be_abstract)
    this->type_ = Type::lookup_float_type("float64");
}

// Check the type of a float value.

void
Float_expression::do_check_types(Gogo*)
{
  Type* type = this->type_;
  if (type == NULL)
    return;
  Numeric_constant nc;
  nc.set_float(NULL, this->val_);
  if (!nc.set_type(this->type_, true, this->location()))
    this->set_is_error();
}

// Get the backend representation for a float constant.

Bexpression*
Float_expression::do_get_backend(Translate_context* context)
{
  if (this->is_error_expression()
      || (this->type_ != NULL && this->type_->is_error_type()))
    {
      go_assert(saw_errors());
      return context->gogo()->backend()->error_expression();
    }

  Type* resolved_type;
  if (this->type_ != NULL && !this->type_->is_abstract())
    resolved_type = this->type_;
  else if (this->type_ != NULL && this->type_->integer_type() != NULL)
    {
      // We have an abstract integer type.  We just hope for the best.
      resolved_type = Type::lookup_integer_type("int");
    }
  else if (this->type_ != NULL && this->type_->complex_type() != NULL)
    {
      // We are converting to an abstract complex type.
      resolved_type = Type::lookup_complex_type("complex128");
    }
  else
    {
      // If we still have an abstract type here, then this is being
      // used in a constant expression which didn't get reduced.  We
      // just use float64 and hope for the best.
      resolved_type = Type::lookup_float_type("float64");
    }

  Numeric_constant nc;
  nc.set_float(resolved_type, this->val_);
  return Expression::backend_numeric_constant_expression(context, &nc);
}

// Write a floating point number to a string dump.

void
Float_expression::export_float(String_dump *exp, const mpfr_t val)
{
  mpfr_exp_t exponent;
  char* s = mpfr_get_str(NULL, &exponent, 10, 0, val, MPFR_RNDN);
  if (*s == '-')
    exp->write_c_string("-");
  exp->write_c_string("0.");
  exp->write_c_string(*s == '-' ? s + 1 : s);
  mpfr_free_str(s);
  char buf[30];
  snprintf(buf, sizeof buf, "E%ld", exponent);
  exp->write_c_string(buf);
}

// Export a floating point number in a constant expression.

void
Float_expression::do_export(Export_function_body* efb) const
{
  bool exported_type = Expression::export_constant_type(efb, this->type_);

  Float_expression::export_float(efb, this->val_);
  // A trailing space lets us reliably identify the end of the number.
  efb->write_c_string(" ");

  Expression::finish_export_constant_type(efb, exported_type);
}

// Dump a floating point number to the dump file.

void
Float_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  Float_expression::export_float(ast_dump_context, this->val_);
}

// Make a float expression.

Expression*
Expression::make_float(const mpfr_t* val, Type* type, Location location)
{
  return new Float_expression(val, type, location);
}

// Complex numbers.

class Complex_expression : public Expression
{
 public:
  Complex_expression(const mpc_t* val, Type* type, Location location)
    : Expression(EXPRESSION_COMPLEX, location),
      type_(type)
  {
    mpc_init2(this->val_, mpc_precision);
    mpc_set(this->val_, *val, MPC_RNDNN);
  }

  // Write VAL to string dump.
  static void
  export_complex(String_dump* exp, const mpc_t val);

  // Write REAL/IMAG to dump context.
  static void
  dump_complex(Ast_dump_context* ast_dump_context, const mpc_t val);

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_is_constant() const
  { return true; }

  bool
  do_is_zero_value() const
  {
    return mpfr_zero_p(mpc_realref(this->val_)) != 0
           && mpfr_signbit(mpc_realref(this->val_)) == 0
           && mpfr_zero_p(mpc_imagref(this->val_)) != 0
           && mpfr_signbit(mpc_imagref(this->val_)) == 0;
  }

  bool
  do_is_static_initializer() const
  { return true; }

  bool
  do_numeric_constant_value(Numeric_constant* nc) const
  {
    nc->set_complex(this->type_, this->val_);
    return true;
  }

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_complex(&this->val_,
				    (this->type_ == NULL
				     ? NULL
				     : this->type_->copy_expressions()),
				    this->location());
  }

  Bexpression*
  do_get_backend(Translate_context*);

  int
  do_inlining_cost() const
  { return 2; }

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The complex value.
  mpc_t val_;
  // The type if known.
  Type* type_;
};

// Traverse a complex expression.  We just need to traverse the type
// if there is one.

int
Complex_expression::do_traverse(Traverse* traverse)
{
  if (this->type_ != NULL)
    return Type::traverse(this->type_, traverse);
  return TRAVERSE_CONTINUE;
}

// Return the current type.  If we haven't set the type yet, we return
// an abstract complex type.

Type*
Complex_expression::do_type()
{
  if (this->type_ == NULL)
    this->type_ = Type::make_abstract_complex_type();
  return this->type_;
}

// Set the type of the complex value.  Here we may switch from an
// abstract type to a real type.

void
Complex_expression::do_determine_type(const Type_context* context)
{
  if (this->type_ != NULL && !this->type_->is_abstract())
    ;
  else if (context->type != NULL && context->type->is_numeric_type())
    this->type_ = context->type;
  else if (!context->may_be_abstract)
    this->type_ = Type::lookup_complex_type("complex128");
}

// Check the type of a complex value.

void
Complex_expression::do_check_types(Gogo*)
{
  Type* type = this->type_;
  if (type == NULL)
    return;
  Numeric_constant nc;
  nc.set_complex(NULL, this->val_);
  if (!nc.set_type(this->type_, true, this->location()))
    this->set_is_error();
}

// Get the backend representation for a complex constant.

Bexpression*
Complex_expression::do_get_backend(Translate_context* context)
{
  if (this->is_error_expression()
      || (this->type_ != NULL && this->type_->is_error_type()))
    {
      go_assert(saw_errors());
      return context->gogo()->backend()->error_expression();
    }

  Type* resolved_type;
  if (this->type_ != NULL && !this->type_->is_abstract())
    resolved_type = this->type_;
  else if (this->type_ != NULL && this->type_->integer_type() != NULL)
    {
      // We are converting to an abstract integer type.
      resolved_type = Type::lookup_integer_type("int");
    }
  else if (this->type_ != NULL && this->type_->float_type() != NULL)
    {
      // We are converting to an abstract float type.
      resolved_type = Type::lookup_float_type("float64");
    }
  else
    {
      // If we still have an abstract type here, this is being
      // used in a constant expression which didn't get reduced.  We
      // just use complex128 and hope for the best.
      resolved_type = Type::lookup_complex_type("complex128");
    }

  Numeric_constant nc;
  nc.set_complex(resolved_type, this->val_);
  return Expression::backend_numeric_constant_expression(context, &nc);
}

// Write REAL/IMAG to export data.

void
Complex_expression::export_complex(String_dump* exp, const mpc_t val)
{
  if (!mpfr_zero_p(mpc_realref(val)))
    {
      Float_expression::export_float(exp, mpc_realref(val));
      if (mpfr_sgn(mpc_imagref(val)) >= 0)
	exp->write_c_string("+");
    }
  Float_expression::export_float(exp, mpc_imagref(val));
  exp->write_c_string("i");
}

// Export a complex number in a constant expression.

void
Complex_expression::do_export(Export_function_body* efb) const
{
  bool exported_type = Expression::export_constant_type(efb, this->type_);

  Complex_expression::export_complex(efb, this->val_);
  // A trailing space lets us reliably identify the end of the number.
  efb->write_c_string(" ");

  Expression::finish_export_constant_type(efb, exported_type);
}

// Dump a complex expression to the dump file.

void
Complex_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  Complex_expression::export_complex(ast_dump_context, this->val_);
}

// Make a complex expression.

Expression*
Expression::make_complex(const mpc_t* val, Type* type, Location location)
{
  return new Complex_expression(val, type, location);
}

// Find a named object in an expression.

class Find_named_object : public Traverse
{
 public:
  Find_named_object(Named_object* no)
    : Traverse(traverse_expressions),
      no_(no), found_(false)
  { }

  // Whether we found the object.
  bool
  found() const
  { return this->found_; }

 protected:
  int
  expression(Expression**);

 private:
  // The object we are looking for.
  Named_object* no_;
  // Whether we found it.
  bool found_;
};

// A reference to a const in an expression.

class Const_expression : public Expression
{
 public:
  Const_expression(Named_object* constant, Location location)
    : Expression(EXPRESSION_CONST_REFERENCE, location),
      constant_(constant), type_(NULL), seen_(false)
  { }

  Named_object*
  named_object()
  { return this->constant_; }

  const Named_object*
  named_object() const
  { return this->constant_; }

  // Check that the initializer does not refer to the constant itself.
  void
  check_for_init_loop();

 protected:
  int
  do_traverse(Traverse*);

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  bool
  do_is_constant() const
  { return true; }

  bool
  do_is_zero_value() const
  { return this->constant_->const_value()->expr()->is_zero_value(); }

  bool
  do_is_static_initializer() const
  { return true; }

  bool
  do_numeric_constant_value(Numeric_constant* nc) const;

  bool
  do_string_constant_value(std::string* val) const;

  bool
  do_boolean_constant_value(bool* val) const;

  Type*
  do_type();

  // The type of a const is set by the declaration, not the use.
  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context* context);

  int
  do_inlining_cost() const
  { return 1; }

  // When exporting a reference to a const as part of a const
  // expression, we export the value.  We ignore the fact that it has
  // a name.
  void
  do_export(Export_function_body* efb) const
  { this->constant_->const_value()->expr()->export_expression(efb); }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The constant.
  Named_object* constant_;
  // The type of this reference.  This is used if the constant has an
  // abstract type.
  Type* type_;
  // Used to prevent infinite recursion when a constant incorrectly
  // refers to itself.
  mutable bool seen_;
};

// Traversal.

int
Const_expression::do_traverse(Traverse* traverse)
{
  if (this->type_ != NULL)
    return Type::traverse(this->type_, traverse);
  return TRAVERSE_CONTINUE;
}

// Lower a constant expression.  This is where we convert the
// predeclared constant iota into an integer value.

Expression*
Const_expression::do_lower(Gogo* gogo, Named_object*,
			   Statement_inserter*, int iota_value)
{
  if (this->constant_->const_value()->expr()->classification()
      == EXPRESSION_IOTA)
    {
      if (iota_value == -1)
	{
	  go_error_at(this->location(),
		      "iota is only defined in const declarations");
	  iota_value = 0;
	}
      return Expression::make_integer_ul(iota_value, NULL, this->location());
    }

  // Make sure that the constant itself has been lowered.
  gogo->lower_constant(this->constant_);

  return this;
}

// Return a numeric constant value.

bool
Const_expression::do_numeric_constant_value(Numeric_constant* nc) const
{
  if (this->seen_)
    return false;

  Expression* e = this->constant_->const_value()->expr();

  this->seen_ = true;

  bool r = e->numeric_constant_value(nc);

  this->seen_ = false;

  Type* ctype;
  if (this->type_ != NULL)
    ctype = this->type_;
  else
    ctype = this->constant_->const_value()->type();
  if (r && ctype != NULL)
    {
      if (!nc->set_type(ctype, false, this->location()))
	return false;
    }

  return r;
}

bool
Const_expression::do_string_constant_value(std::string* val) const
{
  if (this->seen_)
    return false;

  Expression* e = this->constant_->const_value()->expr();

  this->seen_ = true;
  bool ok = e->string_constant_value(val);
  this->seen_ = false;

  return ok;
}

bool
Const_expression::do_boolean_constant_value(bool* val) const
{
  if (this->seen_)
    return false;

  Expression* e = this->constant_->const_value()->expr();

  this->seen_ = true;
  bool ok = e->boolean_constant_value(val);
  this->seen_ = false;

  return ok;
}

// Return the type of the const reference.

Type*
Const_expression::do_type()
{
  if (this->type_ != NULL)
    return this->type_;

  Named_constant* nc = this->constant_->const_value();

  if (this->seen_ || nc->lowering())
    {
      if (nc->type() == NULL || !nc->type()->is_error_type())
	{
	  Location loc = this->location();
	  if (!this->seen_)
	    loc = nc->location();
	  go_error_at(loc, "constant refers to itself");
	}
      this->set_is_error();
      this->type_ = Type::make_error_type();
      nc->set_type(this->type_);
      return this->type_;
    }

  this->seen_ = true;

  Type* ret = nc->type();

  if (ret != NULL)
    {
      this->seen_ = false;
      return ret;
    }

  // During parsing, a named constant may have a NULL type, but we
  // must not return a NULL type here.
  ret = nc->expr()->type();

  this->seen_ = false;

  if (ret->is_error_type())
    nc->set_type(ret);

  return ret;
}

// Set the type of the const reference.

void
Const_expression::do_determine_type(const Type_context* context)
{
  Type* ctype = this->constant_->const_value()->type();
  Type* cetype = (ctype != NULL
		  ? ctype
		  : this->constant_->const_value()->expr()->type());
  if (ctype != NULL && !ctype->is_abstract())
    ;
  else if (context->type != NULL
	   && context->type->is_numeric_type()
	   && cetype->is_numeric_type())
    this->type_ = context->type;
  else if (context->type != NULL
	   && context->type->is_string_type()
	   && cetype->is_string_type())
    this->type_ = context->type;
  else if (context->type != NULL
	   && context->type->is_boolean_type()
	   && cetype->is_boolean_type())
    this->type_ = context->type;
  else if (!context->may_be_abstract)
    {
      if (cetype->is_abstract())
	cetype = cetype->make_non_abstract_type();
      this->type_ = cetype;
    }
}

// Check for a loop in which the initializer of a constant refers to
// the constant itself.

void
Const_expression::check_for_init_loop()
{
  if (this->type_ != NULL && this->type_->is_error())
    return;

  if (this->seen_)
    {
      this->report_error(_("constant refers to itself"));
      this->type_ = Type::make_error_type();
      return;
    }

  Expression* init = this->constant_->const_value()->expr();
  Find_named_object find_named_object(this->constant_);

  this->seen_ = true;
  Expression::traverse(&init, &find_named_object);
  this->seen_ = false;

  if (find_named_object.found())
    {
      if (this->type_ == NULL || !this->type_->is_error())
	{
	  this->report_error(_("constant refers to itself"));
	  this->type_ = Type::make_error_type();
	}
      return;
    }
}

// Check types of a const reference.

void
Const_expression::do_check_types(Gogo*)
{
  if (this->type_ != NULL && this->type_->is_error())
    return;

  this->check_for_init_loop();

  // Check that numeric constant fits in type.
  if (this->type_ != NULL && this->type_->is_numeric_type())
    {
      Numeric_constant nc;
      if (this->constant_->const_value()->expr()->numeric_constant_value(&nc))
	{
	  if (!nc.set_type(this->type_, true, this->location()))
	    this->set_is_error();
	}
    }
}

// Return the backend representation for a const reference.

Bexpression*
Const_expression::do_get_backend(Translate_context* context)
{
  if (this->is_error_expression()
      || (this->type_ != NULL && this->type_->is_error()))
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  // If the type has been set for this expression, but the underlying
  // object is an abstract int or float, we try to get the abstract
  // value.  Otherwise we may lose something in the conversion.
  Expression* expr = this->constant_->const_value()->expr();
  if (this->type_ != NULL
      && this->type_->is_numeric_type()
      && (this->constant_->const_value()->type() == NULL
	  || this->constant_->const_value()->type()->is_abstract()))
    {
      Numeric_constant nc;
      if (expr->numeric_constant_value(&nc)
	  && nc.set_type(this->type_, false, this->location()))
	{
	  Expression* e = nc.expression(this->location());
	  return e->get_backend(context);
	}
    }

  if (this->type_ != NULL)
    expr = Expression::make_cast(this->type_, expr, this->location());
  return expr->get_backend(context);
}

// Dump ast representation for constant expression.

void
Const_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << this->constant_->name();
}

// Make a reference to a constant in an expression.

Expression*
Expression::make_const_reference(Named_object* constant,
				 Location location)
{
  return new Const_expression(constant, location);
}

// Find a named object in an expression.

int
Find_named_object::expression(Expression** pexpr)
{
  switch ((*pexpr)->classification())
    {
    case Expression::EXPRESSION_CONST_REFERENCE:
      {
	Const_expression* ce = static_cast<Const_expression*>(*pexpr);
	if (ce->named_object() == this->no_)
	  break;

	// We need to check a constant initializer explicitly, as
	// loops here will not be caught by the loop checking for
	// variable initializers.
	ce->check_for_init_loop();

	return TRAVERSE_CONTINUE;
      }

    case Expression::EXPRESSION_VAR_REFERENCE:
      if ((*pexpr)->var_expression()->named_object() == this->no_)
	break;
      return TRAVERSE_CONTINUE;
    case Expression::EXPRESSION_FUNC_REFERENCE:
      if ((*pexpr)->func_expression()->named_object() == this->no_)
	break;
      return TRAVERSE_CONTINUE;
    default:
      return TRAVERSE_CONTINUE;
    }
  this->found_ = true;
  return TRAVERSE_EXIT;
}

// The nil value.

class Nil_expression : public Expression
{
 public:
  Nil_expression(Location location)
    : Expression(EXPRESSION_NIL, location)
  { }

  static Expression*
  do_import(Import_expression*, Location);

 protected:
  bool
  do_is_constant() const
  { return true; }

  bool
  do_is_zero_value() const
  { return true; }

  bool
  do_is_static_initializer() const
  { return true; }

  Type*
  do_type()
  { return Type::make_nil_type(); }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context* context)
  { return context->backend()->nil_pointer_expression(); }

  int
  do_inlining_cost() const
  { return 1; }

  void
  do_export(Export_function_body* efb) const
  { efb->write_c_string("$nil"); }

  void
  do_dump_expression(Ast_dump_context* ast_dump_context) const
  { ast_dump_context->ostream() << "nil"; }
};

// Import a nil expression.

Expression*
Nil_expression::do_import(Import_expression* imp, Location loc)
{
  if (imp->version() >= EXPORT_FORMAT_V3)
    imp->require_c_string("$");
  imp->require_c_string("nil");
  return Expression::make_nil(loc);
}

// Make a nil expression.

Expression*
Expression::make_nil(Location location)
{
  return new Nil_expression(location);
}

// The value of the predeclared constant iota.  This is little more
// than a marker.  This will be lowered to an integer in
// Const_expression::do_lower, which is where we know the value that
// it should have.

class Iota_expression : public Parser_expression
{
 public:
  Iota_expression(Location location)
    : Parser_expression(EXPRESSION_IOTA, location)
  { }

 protected:
  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int)
  { go_unreachable(); }

  // There should only ever be one of these.
  Expression*
  do_copy()
  { go_unreachable(); }

  void
  do_dump_expression(Ast_dump_context* ast_dump_context) const
  { ast_dump_context->ostream() << "iota"; }
};

// Make an iota expression.  This is only called for one case: the
// value of the predeclared constant iota.

Expression*
Expression::make_iota()
{
  static Iota_expression iota_expression(Linemap::unknown_location());
  return &iota_expression;
}

// Class Type_conversion_expression.

// Traversal.

int
Type_conversion_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->expr_, traverse) == TRAVERSE_EXIT
      || Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Convert to a constant at lowering time.

Expression*
Type_conversion_expression::do_lower(Gogo*, Named_object*,
				     Statement_inserter*, int)
{
  Type* type = this->type_;
  Expression* val = this->expr_;
  Location location = this->location();

  if (type->is_numeric_type())
    {
      Numeric_constant nc;
      if (val->numeric_constant_value(&nc))
	{
	  if (!nc.set_type(type, true, location))
	    return Expression::make_error(location);
	  return nc.expression(location);
	}
    }

  // According to the language specification on string conversions
  // (http://golang.org/ref/spec#Conversions_to_and_from_a_string_type):
  // When converting an integer into a string, the string will be a UTF-8
  // representation of the integer and integers "outside the range of valid
  // Unicode code points are converted to '\uFFFD'."
  if (type->is_string_type())
    {
      Numeric_constant nc;
      if (val->numeric_constant_value(&nc) && nc.is_int())
        {
          // An integer value doesn't fit in the Unicode code point range if it
          // overflows the Go "int" type or is negative.
          unsigned long ul;
          if (!nc.set_type(Type::lookup_integer_type("int"), false, location)
              || nc.to_unsigned_long(&ul) == Numeric_constant::NC_UL_NEGATIVE)
            return Expression::make_string("\ufffd", location);
        }
    }

  if (type->is_slice_type())
    {
      Type* element_type = type->array_type()->element_type()->forwarded();
      bool is_byte = (element_type->integer_type() != NULL
		      && element_type->integer_type()->is_byte());
      bool is_rune = (element_type->integer_type() != NULL
		      && element_type->integer_type()->is_rune());
      if (is_byte || is_rune)
	{
	  std::string s;
	  if (val->string_constant_value(&s))
	    {
	      Expression_list* vals = new Expression_list();
	      if (is_byte)
		{
		  for (std::string::const_iterator p = s.begin();
		       p != s.end();
		       p++)
		    {
		      unsigned char c = static_cast<unsigned char>(*p);
		      vals->push_back(Expression::make_integer_ul(c,
								  element_type,
								  location));
		    }
		}
	      else
		{
		  const char *p = s.data();
		  const char *pend = s.data() + s.length();
		  while (p < pend)
		    {
		      unsigned int c;
		      int adv = Lex::fetch_char(p, &c);
		      if (adv == 0)
			{
			  go_warning_at(this->location(), 0,
				     "invalid UTF-8 encoding");
			  adv = 1;
			}
		      p += adv;
		      vals->push_back(Expression::make_integer_ul(c,
								  element_type,
								  location));
		    }
		}

	      return Expression::make_slice_composite_literal(type, vals,
							      location);
	    }
	}
    }

  return this;
}

// Flatten a type conversion by using a temporary variable for the slice
// in slice to string conversions.

Expression*
Type_conversion_expression::do_flatten(Gogo*, Named_object*,
                                       Statement_inserter* inserter)
{
  if (this->type()->is_error_type() || this->expr_->is_error_expression())
    {
      go_assert(saw_errors());
      return Expression::make_error(this->location());
    }

  if (((this->type()->is_string_type()
        && this->expr_->type()->is_slice_type())
       || this->expr_->type()->interface_type() != NULL)
      && !this->expr_->is_multi_eval_safe())
    {
      Temporary_statement* temp =
          Statement::make_temporary(NULL, this->expr_, this->location());
      inserter->insert(temp);
      this->expr_ = Expression::make_temporary_reference(temp, this->location());
    }

  // For interface conversion and string to/from slice conversions,
  // decide if we can allocate on stack.
  if (this->type()->interface_type() != NULL
      || this->type()->is_string_type()
      || this->expr_->type()->is_string_type())
    {
      Node* n = Node::make_node(this);
      if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
        this->no_escape_ = true;
    }
  return this;
}

// Return whether a type conversion is a constant.

bool
Type_conversion_expression::do_is_constant() const
{
  if (!this->expr_->is_constant())
    return false;

  // A conversion to a type that may not be used as a constant is not
  // a constant.  For example, []byte(nil).
  Type* type = this->type_;
  if (type->integer_type() == NULL
      && type->float_type() == NULL
      && type->complex_type() == NULL
      && !type->is_boolean_type()
      && !type->is_string_type())
    return false;

  return true;
}

// Return whether a type conversion is a zero value.

bool
Type_conversion_expression::do_is_zero_value() const
{
  if (!this->expr_->is_zero_value())
    return false;

  // Some type conversion from zero value is still not zero value.
  // For example, []byte("") or interface{}(0).
  // Conservatively, only report true if the RHS is nil.
  Type* type = this->type_;
  if (type->integer_type() == NULL
      && type->float_type() == NULL
      && type->complex_type() == NULL
      && !type->is_boolean_type()
      && !type->is_string_type())
    return this->expr_->is_nil_expression();

  return true;
}

// Return whether a type conversion can be used in a constant
// initializer.

bool
Type_conversion_expression::do_is_static_initializer() const
{
  Type* type = this->type_;
  Type* expr_type = this->expr_->type();

  if (type->interface_type() != NULL
      || expr_type->interface_type() != NULL)
    return false;

  if (!this->expr_->is_static_initializer())
    return false;

  if (Type::are_identical(type, expr_type,
			  Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			  NULL))
    return true;

  if (type->is_string_type() && expr_type->is_string_type())
    return true;

  if ((type->is_numeric_type()
       || type->is_boolean_type()
       || type->points_to() != NULL)
      && (expr_type->is_numeric_type()
	  || expr_type->is_boolean_type()
	  || expr_type->points_to() != NULL))
    return true;

  return false;
}

// Return the constant numeric value if there is one.

bool
Type_conversion_expression::do_numeric_constant_value(
    Numeric_constant* nc) const
{
  if (!this->type_->is_numeric_type())
    return false;
  if (!this->expr_->numeric_constant_value(nc))
    return false;
  return nc->set_type(this->type_, false, this->location());
}

// Return the constant string value if there is one.

bool
Type_conversion_expression::do_string_constant_value(std::string* val) const
{
  if (this->type_->is_string_type()
      && this->expr_->type()->integer_type() != NULL)
    {
      Numeric_constant nc;
      if (this->expr_->numeric_constant_value(&nc))
	{
	  unsigned long ival;
	  if (nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID)
	    {
	      unsigned int cval = static_cast<unsigned int>(ival);
	      if (static_cast<unsigned long>(cval) != ival)
		{
		  go_warning_at(this->location(), 0,
				"unicode code point 0x%lx out of range",
				ival);
		  cval = 0xfffd; // Unicode "replacement character."
		}
	      val->clear();
	      Lex::append_char(cval, true, val, this->location());
	      return true;
	    }
	}
    }

  // FIXME: Could handle conversion from const []int here.

  return false;
}

// Return the constant boolean value if there is one.

bool
Type_conversion_expression::do_boolean_constant_value(bool* val) const
{
  if (!this->type_->is_boolean_type())
    return false;
  return this->expr_->boolean_constant_value(val);
}

// Determine the resulting type of the conversion.

void
Type_conversion_expression::do_determine_type(const Type_context*)
{
  Type_context subcontext(this->type_, false);
  this->expr_->determine_type(&subcontext);
}

// Check that types are convertible.

void
Type_conversion_expression::do_check_types(Gogo*)
{
  Type* type = this->type_;
  Type* expr_type = this->expr_->type();
  std::string reason;

  if (type->is_error() || expr_type->is_error())
    {
      this->set_is_error();
      return;
    }

  if (this->may_convert_function_types_
      && type->function_type() != NULL
      && expr_type->function_type() != NULL)
    return;

  if (Type::are_convertible(type, expr_type, &reason))
    return;

  go_error_at(this->location(), "%s", reason.c_str());
  this->set_is_error();
}

// Copy.

Expression*
Type_conversion_expression::do_copy()
{
  Expression* ret = new Type_conversion_expression(this->type_->copy_expressions(),
                                                   this->expr_->copy(),
                                                   this->location());
  ret->conversion_expression()->set_no_copy(this->no_copy_);
  return ret;
}

// Get the backend representation for a type conversion.

Bexpression*
Type_conversion_expression::do_get_backend(Translate_context* context)
{
  Type* type = this->type_;
  Type* expr_type = this->expr_->type();

  Gogo* gogo = context->gogo();
  Btype* btype = type->get_backend(gogo);
  Location loc = this->location();

  if (Type::are_identical(type, expr_type,
			  Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			  NULL))
    {
      Bexpression* bexpr = this->expr_->get_backend(context);
      return gogo->backend()->convert_expression(btype, bexpr, loc);
    }
  else if (type->interface_type() != NULL
           && expr_type->interface_type() == NULL)
    {
      Expression* conversion =
          Expression::convert_type_to_interface(type, this->expr_,
                                                this->no_escape_, loc);
      return conversion->get_backend(context);
    }
  else if (type->interface_type() != NULL
	   || expr_type->interface_type() != NULL)
    {
      Expression* conversion =
          Expression::convert_for_assignment(gogo, type, this->expr_,
                                             loc);
      return conversion->get_backend(context);
    }
  else if (type->is_string_type()
	   && expr_type->integer_type() != NULL)
    {
      mpz_t intval;
      Numeric_constant nc;
      if (this->expr_->numeric_constant_value(&nc)
	  && nc.to_int(&intval))
	{
	  std::string s;
          unsigned int x;
          if (mpz_fits_uint_p(intval))
            x = mpz_get_ui(intval);
          else
            {
              char* ms = mpz_get_str(NULL, 16, intval);
              go_warning_at(loc, 0,
                            "unicode code point 0x%s out of range in string",
                            ms);
              free(ms);
              x = 0xfffd;
            }
	  Lex::append_char(x, true, &s, loc);
	  mpz_clear(intval);
	  Expression* se = Expression::make_string(s, loc);
	  return se->get_backend(context);
	}

      Expression* buf;
      if (this->no_escape_)
        {
          Type* byte_type = Type::lookup_integer_type("uint8");
          Expression* buflen =
            Expression::make_integer_ul(4, NULL, loc);
          Type* array_type = Type::make_array_type(byte_type, buflen);
          buf = Expression::make_allocation(array_type, loc);
          buf->allocation_expression()->set_allocate_on_stack();
          buf->allocation_expression()->set_no_zero();
        }
      else
        buf = Expression::make_nil(loc);
      Expression* i2s_expr =
        Runtime::make_call(Runtime::INTSTRING, loc, 2, buf, this->expr_);
      return Expression::make_cast(type, i2s_expr, loc)->get_backend(context);
    }
  else if (type->is_string_type() && expr_type->is_slice_type())
    {
      Array_type* a = expr_type->array_type();
      Type* e = a->element_type()->forwarded();
      go_assert(e->integer_type() != NULL);
      go_assert(this->expr_->is_multi_eval_safe());

      Expression* buf;
      if (this->no_escape_ && !this->no_copy_)
        {
          Type* byte_type = Type::lookup_integer_type("uint8");
          Expression* buflen =
            Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
          Type* array_type = Type::make_array_type(byte_type, buflen);
          buf = Expression::make_allocation(array_type, loc);
          buf->allocation_expression()->set_allocate_on_stack();
          buf->allocation_expression()->set_no_zero();
        }
      else
        buf = Expression::make_nil(loc);

      if (e->integer_type()->is_byte())
        {
	  Expression* ptr =
	    Expression::make_slice_info(this->expr_, SLICE_INFO_VALUE_POINTER,
					loc);
	  Expression* len =
	    Expression::make_slice_info(this->expr_, SLICE_INFO_LENGTH, loc);
          if (this->no_copy_)
            {
              if (gogo->debug_optimization())
                go_debug(loc, "no copy string([]byte)");
              Expression* str = Expression::make_string_value(ptr, len, loc);
              return str->get_backend(context);
            }
	  return Runtime::make_call(Runtime::SLICEBYTETOSTRING, loc, 3, buf,
				    ptr, len)->get_backend(context);
        }
      else
        {
          go_assert(e->integer_type()->is_rune());
	  return Runtime::make_call(Runtime::SLICERUNETOSTRING, loc, 2, buf,
				    this->expr_)->get_backend(context);
	}
    }
  else if (type->is_slice_type() && expr_type->is_string_type())
    {
      Type* e = type->array_type()->element_type()->forwarded();
      go_assert(e->integer_type() != NULL);

      Runtime::Function code;
      if (e->integer_type()->is_byte())
	code = Runtime::STRINGTOSLICEBYTE;
      else
	{
	  go_assert(e->integer_type()->is_rune());
	  code = Runtime::STRINGTOSLICERUNE;
	}

      Expression* buf;
      if (this->no_escape_)
        {
          Expression* buflen =
            Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
          Type* array_type = Type::make_array_type(e, buflen);
          buf = Expression::make_allocation(array_type, loc);
          buf->allocation_expression()->set_allocate_on_stack();
          buf->allocation_expression()->set_no_zero();
        }
      else
        buf = Expression::make_nil(loc);
      Expression* s2a = Runtime::make_call(code, loc, 2, buf, this->expr_);
      return Expression::make_unsafe_cast(type, s2a, loc)->get_backend(context);
    }
  else if (type->is_numeric_type())
    {
      go_assert(Type::are_convertible(type, expr_type, NULL));
      Bexpression* bexpr = this->expr_->get_backend(context);
      return gogo->backend()->convert_expression(btype, bexpr, loc);
    }
  else if ((type->is_unsafe_pointer_type()
	    && (expr_type->points_to() != NULL
                || expr_type->integer_type()))
           || (expr_type->is_unsafe_pointer_type()
	       && type->points_to() != NULL)
           || (this->may_convert_function_types_
               && type->function_type() != NULL
               && expr_type->function_type() != NULL))
    {
      Bexpression* bexpr = this->expr_->get_backend(context);
      return gogo->backend()->convert_expression(btype, bexpr, loc);
    }
  else
    {
      Expression* conversion =
          Expression::convert_for_assignment(gogo, type, this->expr_, loc);
      return conversion->get_backend(context);
    }
}

// Cost of inlining a type conversion.

int
Type_conversion_expression::do_inlining_cost() const
{
  Type* type = this->type_;
  Type* expr_type = this->expr_->type();
  if (type->interface_type() != NULL || expr_type->interface_type() != NULL)
    return 10;
  else if (type->is_string_type() && expr_type->integer_type() != NULL)
    return 10;
  else if (type->is_string_type() && expr_type->is_slice_type())
    return 10;
  else if (type->is_slice_type() && expr_type->is_string_type())
    return 10;
  else
    return 1;
}

// Output a type conversion in a constant expression.

void
Type_conversion_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("$convert(");
  efb->write_type(this->type_);
  efb->write_c_string(", ");

  Type* old_context = efb->type_context();
  efb->set_type_context(this->type_);

  this->expr_->export_expression(efb);

  efb->set_type_context(old_context);

  efb->write_c_string(")");
}

// Import a type conversion or a struct construction.

Expression*
Type_conversion_expression::do_import(Import_expression* imp, Location loc)
{
  imp->require_c_string("$convert(");
  Type* type = imp->read_type();
  imp->require_c_string(", ");
  Expression* val = Expression::import_expression(imp, loc);
  imp->require_c_string(")");
  return Expression::make_cast(type, val, loc);
}

// Dump ast representation for a type conversion expression.

void
Type_conversion_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << "(";
  ast_dump_context->dump_expression(this->expr_);
  ast_dump_context->ostream() << ") ";
}

// Make a type cast expression.

Expression*
Expression::make_cast(Type* type, Expression* val, Location location)
{
  if (type->is_error_type() || val->is_error_expression())
    return Expression::make_error(location);
  return new Type_conversion_expression(type, val, location);
}

// Class Unsafe_type_conversion_expression.

// Traversal.

int
Unsafe_type_conversion_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->expr_, traverse) == TRAVERSE_EXIT
      || Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Return whether an unsafe type conversion can be used as a constant
// initializer.

bool
Unsafe_type_conversion_expression::do_is_static_initializer() const
{
  Type* type = this->type_;
  Type* expr_type = this->expr_->type();

  if (type->interface_type() != NULL
      || expr_type->interface_type() != NULL)
    return false;

  if (!this->expr_->is_static_initializer())
    return false;

  if (Type::are_convertible(type, expr_type, NULL))
    return true;

  if (type->is_string_type() && expr_type->is_string_type())
    return true;

  if ((type->is_numeric_type()
       || type->is_boolean_type()
       || type->points_to() != NULL)
      && (expr_type->is_numeric_type()
	  || expr_type->is_boolean_type()
	  || expr_type->points_to() != NULL))
    return true;

  return false;
}

// Copy.

Expression*
Unsafe_type_conversion_expression::do_copy()
{
  return new Unsafe_type_conversion_expression(this->type_->copy_expressions(),
					       this->expr_->copy(),
					       this->location());
}

// Convert to backend representation.

Bexpression*
Unsafe_type_conversion_expression::do_get_backend(Translate_context* context)
{
  // We are only called for a limited number of cases.

  Type* t = this->type_;
  Type* et = this->expr_->type();

  if (t->is_error_type()
      || this->expr_->is_error_expression()
      || et->is_error_type())
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  if (t->array_type() != NULL)
    go_assert(et->array_type() != NULL
              && t->is_slice_type() == et->is_slice_type());
  else if (t->struct_type() != NULL)
    {
      if (t->named_type() != NULL
          && et->named_type() != NULL
          && !Type::are_convertible(t, et, NULL))
	{
	  go_assert(saw_errors());
	  return context->backend()->error_expression();
	}

      go_assert(et->struct_type() != NULL
                && Type::are_convertible(t, et, NULL));
    }
  else if (t->map_type() != NULL)
    go_assert(et->map_type() != NULL || et->points_to() != NULL);
  else if (t->channel_type() != NULL)
    go_assert(et->channel_type() != NULL || et->points_to() != NULL);
  else if (t->points_to() != NULL)
    go_assert(et->points_to() != NULL
              || et->channel_type() != NULL
              || et->map_type() != NULL
              || et->function_type() != NULL
	      || et->integer_type() != NULL
              || et->is_nil_type());
  else if (t->function_type() != NULL)
    go_assert(et->points_to() != NULL);
  else if (et->is_unsafe_pointer_type())
    go_assert(t->points_to() != NULL
	      || (t->integer_type() != NULL
		  && t->integer_type() == Type::lookup_integer_type("uintptr")->real_type()));
  else if (t->interface_type() != NULL)
    {
      bool empty_iface = t->interface_type()->is_empty();
      go_assert(et->interface_type() != NULL
                && et->interface_type()->is_empty() == empty_iface);
    }
  else if (t->integer_type() != NULL)
    go_assert(et->is_boolean_type()
              || et->integer_type() != NULL
              || et->function_type() != NULL
              || et->points_to() != NULL
              || et->map_type() != NULL
              || et->channel_type() != NULL
	      || et->is_nil_type());
  else
    go_unreachable();

  Gogo* gogo = context->gogo();
  Btype* btype = t->get_backend(gogo);
  Bexpression* bexpr = this->expr_->get_backend(context);
  Location loc = this->location();
  return gogo->backend()->convert_expression(btype, bexpr, loc);
}

// Dump ast representation for an unsafe type conversion expression.

void
Unsafe_type_conversion_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << "(";
  ast_dump_context->dump_expression(this->expr_);
  ast_dump_context->ostream() << ") ";
}

// Make an unsafe type conversion expression.

Expression*
Expression::make_unsafe_cast(Type* type, Expression* expr,
			     Location location)
{
  return new Unsafe_type_conversion_expression(type, expr, location);
}

// Class Unary_expression.

// Call the address_taken method of the operand if needed.  This is
// called after escape analysis but before inserting write barriers.

void
Unary_expression::check_operand_address_taken(Gogo*)
{
  if (this->op_ != OPERATOR_AND)
    return;

  // If this->escapes_ is false at this point, then it was set to
  // false by an explicit call to set_does_not_escape, and the value
  // does not escape.  If this->escapes_ is true, we may be able to
  // set it to false based on the escape analysis pass.
  if (this->escapes_)
    {
      Node* n = Node::make_node(this);
      if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
	this->escapes_ = false;
    }

  this->expr_->address_taken(this->escapes_);
}

// If we are taking the address of a composite literal, and the
// contents are not constant, then we want to make a heap expression
// instead.

Expression*
Unary_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
{
  Location loc = this->location();
  Operator op = this->op_;
  Expression* expr = this->expr_;

  if (op == OPERATOR_MULT && expr->is_type_expression())
    return Expression::make_type(Type::make_pointer_type(expr->type()), loc);

  // *&x simplifies to x.  *(*T)(unsafe.Pointer)(&x) does not require
  // moving x to the heap.  FIXME: Is it worth doing a real escape
  // analysis here?  This case is found in math/unsafe.go and is
  // therefore worth special casing.
  if (op == OPERATOR_MULT)
    {
      Expression* e = expr;
      while (e->classification() == EXPRESSION_CONVERSION)
	{
	  Type_conversion_expression* te
	    = static_cast<Type_conversion_expression*>(e);
	  e = te->expr();
	}

      if (e->classification() == EXPRESSION_UNARY)
	{
	  Unary_expression* ue = static_cast<Unary_expression*>(e);
	  if (ue->op_ == OPERATOR_AND)
	    {
	      if (e == expr)
		{
		  // *&x == x.
		  if (!ue->expr_->is_addressable() && !ue->create_temp_)
		    {
		      go_error_at(ue->location(),
				  "invalid operand for unary %<&%>");
		      this->set_is_error();
		    }
		  return ue->expr_;
		}
	      ue->set_does_not_escape();
	    }
	}
    }

  // Catching an invalid indirection of unsafe.Pointer here avoid
  // having to deal with TYPE_VOID in other places.
  if (op == OPERATOR_MULT && expr->type()->is_unsafe_pointer_type())
    {
      go_error_at(this->location(), "invalid indirect of %<unsafe.Pointer%>");
      return Expression::make_error(this->location());
    }

  // Check for an invalid pointer dereference.  We need to do this
  // here because Unary_expression::do_type will return an error type
  // in this case.  That can cause code to appear erroneous, and
  // therefore disappear at lowering time, without any error message.
  if (op == OPERATOR_MULT && expr->type()->points_to() == NULL)
    {
      this->report_error(_("expected pointer"));
      return Expression::make_error(this->location());
    }

  if (op == OPERATOR_PLUS || op == OPERATOR_MINUS || op == OPERATOR_XOR)
    {
      Numeric_constant nc;
      if (expr->numeric_constant_value(&nc))
	{
	  Numeric_constant result;
	  bool issued_error;
	  if (Unary_expression::eval_constant(op, &nc, loc, &result,
					      &issued_error))
	    return result.expression(loc);
	  else if (issued_error)
	    return Expression::make_error(this->location());
	}
    }

  return this;
}

// Flatten expression if a nil check must be performed and create temporary
// variables if necessary.

Expression*
Unary_expression::do_flatten(Gogo* gogo, Named_object*,
                             Statement_inserter* inserter)
{
  if (this->is_error_expression()
      || this->expr_->is_error_expression()
      || this->expr_->type()->is_error_type())
    {
      go_assert(saw_errors());
      return Expression::make_error(this->location());
    }

  Location location = this->location();
  if (this->op_ == OPERATOR_MULT
      && !this->expr_->is_multi_eval_safe())
    {
      go_assert(this->expr_->type()->points_to() != NULL);
      switch (this->requires_nil_check(gogo))
        {
          case NIL_CHECK_ERROR_ENCOUNTERED:
            {
              go_assert(saw_errors());
              return Expression::make_error(this->location());
            }
          case NIL_CHECK_NOT_NEEDED:
            break;
          case NIL_CHECK_NEEDED:
            this->create_temp_ = true;
            break;
          case NIL_CHECK_DEFAULT:
            go_unreachable();
        }
    }

  if (this->create_temp_ && !this->expr_->is_multi_eval_safe())
    {
      Temporary_statement* temp =
          Statement::make_temporary(NULL, this->expr_, location);
      inserter->insert(temp);
      this->expr_ = Expression::make_temporary_reference(temp, location);
    }

  return this;
}

// Return whether a unary expression is a constant.

bool
Unary_expression::do_is_constant() const
{
  if (this->op_ == OPERATOR_MULT)
    {
      // Indirecting through a pointer is only constant if the object
      // to which the expression points is constant, but we currently
      // have no way to determine that.
      return false;
    }
  else if (this->op_ == OPERATOR_AND)
    {
      // Taking the address of a variable is constant if it is a
      // global variable, not constant otherwise.  In other cases taking the
      // address is probably not a constant.
      Var_expression* ve = this->expr_->var_expression();
      if (ve != NULL)
	{
	  Named_object* no = ve->named_object();
	  return no->is_variable() && no->var_value()->is_global();
	}
      return false;
    }
  else
    return this->expr_->is_constant();
}

// Return whether a unary expression can be used as a constant
// initializer.

bool
Unary_expression::do_is_static_initializer() const
{
  if (this->op_ == OPERATOR_MULT)
    return false;
  else if (this->op_ == OPERATOR_AND)
    return Unary_expression::base_is_static_initializer(this->expr_);
  else
    return this->expr_->is_static_initializer();
}

// Return whether the address of EXPR can be used as a static
// initializer.

bool
Unary_expression::base_is_static_initializer(Expression* expr)
{
  // The address of a field reference can be a static initializer if
  // the base can be a static initializer.
  Field_reference_expression* fre = expr->field_reference_expression();
  if (fre != NULL)
    return Unary_expression::base_is_static_initializer(fre->expr());

  // The address of an index expression can be a static initializer if
  // the base can be a static initializer and the index is constant.
  Array_index_expression* aind = expr->array_index_expression();
  if (aind != NULL)
    return (aind->end() == NULL
	    && aind->start()->is_constant()
	    && Unary_expression::base_is_static_initializer(aind->array()));

  // The address of a global variable can be a static initializer.
  Var_expression* ve = expr->var_expression();
  if (ve != NULL)
    {
      Named_object* no = ve->named_object();
      return no->is_variable() && no->var_value()->is_global();
    }

  // The address of a composite literal can be used as a static
  // initializer if the composite literal is itself usable as a
  // static initializer.
  if (expr->is_composite_literal() && expr->is_static_initializer())
    return true;

  // The address of a string constant can be used as a static
  // initializer.  This can not be written in Go itself but this is
  // used when building a type descriptor.
  if (expr->string_expression() != NULL)
    return true;

  return false;
}

// Return whether this dereference expression requires an explicit nil
// check. If we are dereferencing the pointer to a large struct
// (greater than the specified size threshold), we need to check for
// nil. We don't bother to check for small structs because we expect
// the system to crash on a nil pointer dereference. However, if we
// know the address of this expression is being taken, we must always
// check for nil.
Unary_expression::Nil_check_classification
Unary_expression::requires_nil_check(Gogo* gogo)
{
  go_assert(this->op_ == OPERATOR_MULT);
  go_assert(this->expr_->type()->points_to() != NULL);

  if (this->issue_nil_check_ == NIL_CHECK_NEEDED)
    return NIL_CHECK_NEEDED;
  else if (this->issue_nil_check_ == NIL_CHECK_NOT_NEEDED)
    return NIL_CHECK_NOT_NEEDED;

  Type* ptype = this->expr_->type()->points_to();
  int64_t type_size = -1;
  if (!ptype->is_void_type())
    {
      bool ok = ptype->backend_type_size(gogo, &type_size);
      if (!ok)
        return NIL_CHECK_ERROR_ENCOUNTERED;
    }

  int64_t size_cutoff = gogo->nil_check_size_threshold();
  if (size_cutoff == -1 || (type_size != -1 && type_size >= size_cutoff))
    this->issue_nil_check_ = NIL_CHECK_NEEDED;
  else
    this->issue_nil_check_ = NIL_CHECK_NOT_NEEDED;
  return this->issue_nil_check_;
}

// Apply unary opcode OP to UNC, setting NC.  Return true if this
// could be done, false if not.  On overflow, issues an error and sets
// *ISSUED_ERROR.

bool
Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
				Location location, Numeric_constant* nc,
				bool* issued_error)
{
  *issued_error = false;
  switch (op)
    {
    case OPERATOR_PLUS:
      *nc = *unc;
      return true;

    case OPERATOR_MINUS:
      if (unc->is_int() || unc->is_rune())
	break;
      else if (unc->is_float())
	{
	  mpfr_t uval;
	  unc->get_float(&uval);
	  mpfr_t val;
	  mpfr_init(val);
	  mpfr_neg(val, uval, MPFR_RNDN);
	  nc->set_float(unc->type(), val);
	  mpfr_clear(uval);
	  mpfr_clear(val);
	  return true;
	}
      else if (unc->is_complex())
	{
	  mpc_t uval;
	  unc->get_complex(&uval);
	  mpc_t val;
	  mpc_init2(val, mpc_precision);
	  mpc_neg(val, uval, MPC_RNDNN);
	  nc->set_complex(unc->type(), val);
	  mpc_clear(uval);
	  mpc_clear(val);
	  return true;
	}
      else
	go_unreachable();

    case OPERATOR_XOR:
      break;

    case OPERATOR_NOT:
    case OPERATOR_AND:
    case OPERATOR_MULT:
      return false;

    default:
      go_unreachable();
    }

  if (!unc->is_int() && !unc->is_rune())
    return false;

  mpz_t uval;
  if (unc->is_rune())
    unc->get_rune(&uval);
  else
    unc->get_int(&uval);
  mpz_t val;
  mpz_init(val);

  switch (op)
    {
    case OPERATOR_MINUS:
      mpz_neg(val, uval);
      break;

    case OPERATOR_NOT:
      mpz_set_ui(val, mpz_cmp_si(uval, 0) == 0 ? 1 : 0);
      break;

    case OPERATOR_XOR:
      {
	Type* utype = unc->type();
	if (utype->integer_type() == NULL
	    || utype->integer_type()->is_abstract())
	  mpz_com(val, uval);
	else
	  {
	    // The number of HOST_WIDE_INTs that it takes to represent
	    // UVAL.
	    size_t count = ((mpz_sizeinbase(uval, 2)
			     + HOST_BITS_PER_WIDE_INT
			     - 1)
			    / HOST_BITS_PER_WIDE_INT);

	    unsigned HOST_WIDE_INT* phwi = new unsigned HOST_WIDE_INT[count];
	    memset(phwi, 0, count * sizeof(HOST_WIDE_INT));

	    size_t obits = utype->integer_type()->bits();

	    if (!utype->integer_type()->is_unsigned() && mpz_sgn(uval) < 0)
	      {
		mpz_t adj;
		mpz_init_set_ui(adj, 1);
		mpz_mul_2exp(adj, adj, obits);
		mpz_add(uval, uval, adj);
		mpz_clear(adj);
	      }

	    size_t ecount;
	    mpz_export(phwi, &ecount, -1, sizeof(HOST_WIDE_INT), 0, 0, uval);
	    go_assert(ecount <= count);

	    // Trim down to the number of words required by the type.
	    size_t ocount = ((obits + HOST_BITS_PER_WIDE_INT - 1)
			     / HOST_BITS_PER_WIDE_INT);
	    go_assert(ocount <= count);

	    for (size_t i = 0; i < ocount; ++i)
	      phwi[i] = ~phwi[i];

	    size_t clearbits = ocount * HOST_BITS_PER_WIDE_INT - obits;
	    if (clearbits != 0)
	      phwi[ocount - 1] &= (((unsigned HOST_WIDE_INT) (HOST_WIDE_INT) -1)
				   >> clearbits);

	    mpz_import(val, ocount, -1, sizeof(HOST_WIDE_INT), 0, 0, phwi);

	    if (!utype->integer_type()->is_unsigned()
		&& mpz_tstbit(val, obits - 1))
	      {
		mpz_t adj;
		mpz_init_set_ui(adj, 1);
		mpz_mul_2exp(adj, adj, obits);
		mpz_sub(val, val, adj);
		mpz_clear(adj);
	      }

	    delete[] phwi;
	  }
      }
      break;

    default:
      go_unreachable();
    }

  if (unc->is_rune())
    nc->set_rune(NULL, val);
  else
    nc->set_int(NULL, val);

  mpz_clear(uval);
  mpz_clear(val);

  if (!nc->set_type(unc->type(), true, location))
    {
      *issued_error = true;
      return false;
    }
  return true;
}

// Return the integral constant value of a unary expression, if it has one.

bool
Unary_expression::do_numeric_constant_value(Numeric_constant* nc) const
{
  Numeric_constant unc;
  if (!this->expr_->numeric_constant_value(&unc))
    return false;
  bool issued_error;
  return Unary_expression::eval_constant(this->op_, &unc, this->location(),
					 nc, &issued_error);
}

// Return the boolean constant value of a unary expression, if it has one.

bool
Unary_expression::do_boolean_constant_value(bool* val) const
{
  if (this->op_ == OPERATOR_NOT
      && this->expr_->boolean_constant_value(val))
    {
      *val = !*val;
      return true;
    }
  return false;
}

// Return the type of a unary expression.

Type*
Unary_expression::do_type()
{
  switch (this->op_)
    {
    case OPERATOR_PLUS:
    case OPERATOR_MINUS:
    case OPERATOR_NOT:
    case OPERATOR_XOR:
      return this->expr_->type();

    case OPERATOR_AND:
      return Type::make_pointer_type(this->expr_->type());

    case OPERATOR_MULT:
      {
	Type* subtype = this->expr_->type();
	Type* points_to = subtype->points_to();
	if (points_to == NULL)
	  return Type::make_error_type();
	return points_to;
      }

    default:
      go_unreachable();
    }
}

// Determine abstract types for a unary expression.

void
Unary_expression::do_determine_type(const Type_context* context)
{
  switch (this->op_)
    {
    case OPERATOR_PLUS:
    case OPERATOR_MINUS:
    case OPERATOR_NOT:
    case OPERATOR_XOR:
      this->expr_->determine_type(context);
      break;

    case OPERATOR_AND:
      // Taking the address of something.
      {
	Type* subtype = (context->type == NULL
			 ? NULL
			 : context->type->points_to());
	Type_context subcontext(subtype, false);
	this->expr_->determine_type(&subcontext);
      }
      break;

    case OPERATOR_MULT:
      // Indirecting through a pointer.
      {
	Type* subtype = (context->type == NULL
			 ? NULL
			 : Type::make_pointer_type(context->type));
	Type_context subcontext(subtype, false);
	this->expr_->determine_type(&subcontext);
      }
      break;

    default:
      go_unreachable();
    }
}

// Check types for a unary expression.

void
Unary_expression::do_check_types(Gogo*)
{
  Type* type = this->expr_->type();
  if (type->is_error())
    {
      this->set_is_error();
      return;
    }

  switch (this->op_)
    {
    case OPERATOR_PLUS:
    case OPERATOR_MINUS:
      if (type->integer_type() == NULL
	  && type->float_type() == NULL
	  && type->complex_type() == NULL)
	this->report_error(_("expected numeric type"));
      break;

    case OPERATOR_NOT:
      if (!type->is_boolean_type())
	this->report_error(_("expected boolean type"));
      break;

    case OPERATOR_XOR:
      if (type->integer_type() == NULL)
	this->report_error(_("expected integer"));
      break;

    case OPERATOR_AND:
      if (!this->expr_->is_addressable())
	{
	  if (!this->create_temp_)
	    {
	      go_error_at(this->location(), "invalid operand for unary %<&%>");
	      this->set_is_error();
	    }
	}
      else
	this->expr_->issue_nil_check();
      break;

    case OPERATOR_MULT:
      // Indirecting through a pointer.
      if (type->points_to() == NULL)
	this->report_error(_("expected pointer"));
      if (type->points_to()->is_error())
	this->set_is_error();
      break;

    default:
      go_unreachable();
    }
}

// Get the backend representation for a unary expression.

Bexpression*
Unary_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Location loc = this->location();

  // Taking the address of a set-and-use-temporary expression requires
  // setting the temporary and then taking the address.
  if (this->op_ == OPERATOR_AND)
    {
      Set_and_use_temporary_expression* sut =
	this->expr_->set_and_use_temporary_expression();
      if (sut != NULL)
	{
	  Temporary_statement* temp = sut->temporary();
	  Bvariable* bvar = temp->get_backend_variable(context);
          Bexpression* bvar_expr =
              gogo->backend()->var_expression(bvar, loc);
          Bexpression* bval = sut->expression()->get_backend(context);

          Named_object* fn = context->function();
          go_assert(fn != NULL);
          Bfunction* bfn =
              fn->func_value()->get_or_make_decl(gogo, fn);
          Bstatement* bassign =
              gogo->backend()->assignment_statement(bfn, bvar_expr, bval, loc);
          Bexpression* bvar_addr =
              gogo->backend()->address_expression(bvar_expr, loc);
	  return gogo->backend()->compound_expression(bassign, bvar_addr, loc);
	}
    }

  Bexpression* ret;
  Bexpression* bexpr = this->expr_->get_backend(context);
  Btype* btype = this->expr_->type()->get_backend(gogo);
  switch (this->op_)
    {
    case OPERATOR_PLUS:
      ret = bexpr;
      break;

    case OPERATOR_MINUS:
      ret = gogo->backend()->unary_expression(this->op_, bexpr, loc);
      ret = gogo->backend()->convert_expression(btype, ret, loc);
      break;

    case OPERATOR_NOT:
    case OPERATOR_XOR:
      ret = gogo->backend()->unary_expression(this->op_, bexpr, loc);
      break;

    case OPERATOR_AND:
      if (!this->create_temp_)
	{
	  // We should not see a non-constant constructor here; cases
	  // where we would see one should have been moved onto the
	  // heap at parse time.  Taking the address of a nonconstant
	  // constructor will not do what the programmer expects.

          go_assert(!this->expr_->is_composite_literal()
                    || this->expr_->is_static_initializer());
	  if (this->expr_->classification() == EXPRESSION_UNARY)
	    {
	      Unary_expression* ue =
		static_cast<Unary_expression*>(this->expr_);
	      go_assert(ue->op() != OPERATOR_AND);
	    }
	}

      if (this->is_gc_root_ || this->is_slice_init_)
	{
	  std::string var_name;
	  bool copy_to_heap = false;
	  if (this->is_gc_root_)
	    {
	      // Build a decl for a GC root variable.  GC roots are mutable, so
	      // they cannot be represented as an immutable_struct in the
	      // backend.
	      var_name = gogo->gc_root_name();
	    }
	  else
	    {
	      // Build a decl for a slice value initializer.  An immutable slice
	      // value initializer may have to be copied to the heap if it
	      // contains pointers in a non-constant context.
	      var_name = gogo->initializer_name();

	      Array_type* at = this->expr_->type()->array_type();
	      go_assert(at != NULL);

	      // If we are not copying the value to the heap, we will only
	      // initialize the value once, so we can use this directly
	      // rather than copying it.  In that case we can't make it
	      // read-only, because the program is permitted to change it.
	      copy_to_heap = (context->function() != NULL
                              || context->is_const());
	    }
	  unsigned int flags = (Backend::variable_is_hidden
				| Backend::variable_address_is_taken);
	  if (copy_to_heap)
	    flags |= Backend::variable_is_constant;
	  Bvariable* implicit =
	    gogo->backend()->implicit_variable(var_name, "", btype, flags, 0);
	  gogo->backend()->implicit_variable_set_init(implicit, var_name, btype,
						      flags, bexpr);
	  bexpr = gogo->backend()->var_expression(implicit, loc);

	  // If we are not copying a slice initializer to the heap,
	  // then it can be changed by the program, so if it can
	  // contain pointers we must register it as a GC root.
	  if (this->is_slice_init_
	      && !copy_to_heap
	      && this->expr_->type()->has_pointer())
	    {
	      Bexpression* root =
                  gogo->backend()->var_expression(implicit, loc);
	      root = gogo->backend()->address_expression(root, loc);
	      Type* type = Type::make_pointer_type(this->expr_->type());
	      gogo->add_gc_root(Expression::make_backend(root, type, loc));
	    }
	}
      else if ((this->expr_->is_composite_literal()
		|| this->expr_->string_expression() != NULL)
	       && this->expr_->is_static_initializer())
        {
	  std::string var_name(gogo->initializer_name());
	  unsigned int flags = (Backend::variable_is_hidden
				| Backend::variable_address_is_taken);
          Bvariable* decl =
	    gogo->backend()->immutable_struct(var_name, "", flags, btype, loc);
          gogo->backend()->immutable_struct_set_init(decl, var_name, flags,
						     btype, loc, bexpr);
          bexpr = gogo->backend()->var_expression(decl, loc);
        }
      else if (this->expr_->is_constant())
        {
          std::string var_name(gogo->initializer_name());
	  unsigned int flags = (Backend::variable_is_hidden
				| Backend::variable_is_constant
				| Backend::variable_address_is_taken);
          Bvariable* decl =
	    gogo->backend()->implicit_variable(var_name, "", btype, flags, 0);
          gogo->backend()->implicit_variable_set_init(decl, var_name, btype,
						      flags, bexpr);
          bexpr = gogo->backend()->var_expression(decl, loc);
        }

      go_assert(!this->create_temp_ || this->expr_->is_multi_eval_safe());
      ret = gogo->backend()->address_expression(bexpr, loc);
      break;

    case OPERATOR_MULT:
      {
        go_assert(this->expr_->type()->points_to() != NULL);

        Type* ptype = this->expr_->type()->points_to();
        Btype* pbtype = ptype->get_backend(gogo);
        switch (this->requires_nil_check(gogo))
          {
            case NIL_CHECK_NOT_NEEDED:
              break;
            case NIL_CHECK_ERROR_ENCOUNTERED:
              {
                go_assert(saw_errors());
                return gogo->backend()->error_expression();
              }
            case NIL_CHECK_NEEDED:
              {
                go_assert(this->expr_->is_multi_eval_safe());

                // If we're nil-checking the result of a set-and-use-temporary
                // expression, then pick out the target temp and use that
                // for the final result of the conditional.
                Bexpression* tbexpr = bexpr;
                Bexpression* ubexpr = bexpr;
                Set_and_use_temporary_expression* sut =
                    this->expr_->set_and_use_temporary_expression();
                if (sut != NULL) {
                  Temporary_statement* temp = sut->temporary();
                  Bvariable* bvar = temp->get_backend_variable(context);
                  ubexpr = gogo->backend()->var_expression(bvar, loc);
                }
                Bexpression* nil =
                    Expression::make_nil(loc)->get_backend(context);
                Bexpression* compare =
                    gogo->backend()->binary_expression(OPERATOR_EQEQ, tbexpr,
                                                       nil, loc);
		Expression* crash = Runtime::make_call(Runtime::PANIC_MEM,
						       loc, 0);
		Bexpression* bcrash = crash->get_backend(context);
                Bfunction* bfn = context->function()->func_value()->get_decl();
                bexpr = gogo->backend()->conditional_expression(bfn, btype,
                                                                compare,
                                                                bcrash, ubexpr,
                                                                loc);
                break;
              }
            case NIL_CHECK_DEFAULT:
              go_unreachable();
          }
        ret = gogo->backend()->indirect_expression(pbtype, bexpr, false, loc);
      }
      break;

    default:
      go_unreachable();
    }

  return ret;
}

// Export a unary expression.

void
Unary_expression::do_export(Export_function_body* efb) const
{
  switch (this->op_)
    {
    case OPERATOR_PLUS:
      efb->write_c_string("+");
      break;
    case OPERATOR_MINUS:
      efb->write_c_string("-");
      break;
    case OPERATOR_NOT:
      efb->write_c_string("!");
      break;
    case OPERATOR_XOR:
      efb->write_c_string("^");
      break;
    case OPERATOR_AND:
      efb->write_c_string("&");
      break;
    case OPERATOR_MULT:
      efb->write_c_string("*");
      break;
    default:
      go_unreachable();
    }
  this->expr_->export_expression(efb);
}

// Import a unary expression.

Expression*
Unary_expression::do_import(Import_expression* imp, Location loc)
{
  Operator op;
  switch (imp->get_char())
    {
    case '+':
      op = OPERATOR_PLUS;
      break;
    case '-':
      op = OPERATOR_MINUS;
      break;
    case '!':
      op = OPERATOR_NOT;
      break;
    case '^':
      op = OPERATOR_XOR;
      break;
    case '&':
      op = OPERATOR_AND;
      break;
    case '*':
      op = OPERATOR_MULT;
      break;
    default:
      go_unreachable();
    }
  if (imp->version() < EXPORT_FORMAT_V3)
    imp->require_c_string(" ");
  Expression* expr = Expression::import_expression(imp, loc);
  return Expression::make_unary(op, expr, loc);
}

// Dump ast representation of an unary expression.

void
Unary_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->dump_operator(this->op_);
  ast_dump_context->ostream() << "(";
  ast_dump_context->dump_expression(this->expr_);
  ast_dump_context->ostream() << ") ";
}

// Make a unary expression.

Expression*
Expression::make_unary(Operator op, Expression* expr, Location location)
{
  return new Unary_expression(op, expr, location);
}

Expression*
Expression::make_dereference(Expression* ptr,
                             Nil_check_classification docheck,
                             Location location)
{
  Expression* deref = Expression::make_unary(OPERATOR_MULT, ptr, location);
  if (docheck == NIL_CHECK_NEEDED)
    deref->unary_expression()->set_requires_nil_check(true);
  else if (docheck == NIL_CHECK_NOT_NEEDED)
    deref->unary_expression()->set_requires_nil_check(false);
  return deref;
}

// If this is an indirection through a pointer, return the expression
// being pointed through.  Otherwise return this.

Expression*
Expression::deref()
{
  if (this->classification_ == EXPRESSION_UNARY)
    {
      Unary_expression* ue = static_cast<Unary_expression*>(this);
      if (ue->op() == OPERATOR_MULT)
	return ue->operand();
    }
  return this;
}

// Class Binary_expression.

// Traversal.

int
Binary_expression::do_traverse(Traverse* traverse)
{
  int t = Expression::traverse(&this->left_, traverse);
  if (t == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return Expression::traverse(&this->right_, traverse);
}

// Return whether this expression may be used as a static initializer.

bool
Binary_expression::do_is_static_initializer() const
{
  if (!this->left_->is_static_initializer()
      || !this->right_->is_static_initializer())
    return false;

  // Addresses can be static initializers, but we can't implement
  // arbitray binary expressions of them.
  Unary_expression* lu = this->left_->unary_expression();
  Unary_expression* ru = this->right_->unary_expression();
  if (lu != NULL && lu->op() == OPERATOR_AND)
    {
      if (ru != NULL && ru->op() == OPERATOR_AND)
	return this->op_ == OPERATOR_MINUS;
      else
	return this->op_ == OPERATOR_PLUS || this->op_ == OPERATOR_MINUS;
    }
  else if (ru != NULL && ru->op() == OPERATOR_AND)
    return this->op_ == OPERATOR_PLUS || this->op_ == OPERATOR_MINUS;

  // Other cases should resolve in the backend.
  return true;
}

// Return the type to use for a binary operation on operands of
// LEFT_TYPE and RIGHT_TYPE.  These are the types of constants and as
// such may be NULL or abstract.

bool
Binary_expression::operation_type(Operator op, Type* left_type,
				  Type* right_type, Type** result_type)
{
  if (left_type != right_type
      && !left_type->is_abstract()
      && !right_type->is_abstract()
      && left_type->base() != right_type->base()
      && op != OPERATOR_LSHIFT
      && op != OPERATOR_RSHIFT)
    {
      // May be a type error--let it be diagnosed elsewhere.
      return false;
    }

  if (op == OPERATOR_LSHIFT || op == OPERATOR_RSHIFT)
    {
      if (left_type->integer_type() != NULL)
	*result_type = left_type;
      else
	*result_type = Type::make_abstract_integer_type();
    }
  else if (!left_type->is_abstract() && left_type->named_type() != NULL)
    *result_type = left_type;
  else if (!right_type->is_abstract() && right_type->named_type() != NULL)
    *result_type = right_type;
  else if (!left_type->is_abstract())
    *result_type = left_type;
  else if (!right_type->is_abstract())
    *result_type = right_type;
  else if (left_type->complex_type() != NULL)
    *result_type = left_type;
  else if (right_type->complex_type() != NULL)
    *result_type = right_type;
  else if (left_type->float_type() != NULL)
    *result_type = left_type;
  else if (right_type->float_type() != NULL)
    *result_type = right_type;
  else if (left_type->integer_type() != NULL
	   && left_type->integer_type()->is_rune())
    *result_type = left_type;
  else if (right_type->integer_type() != NULL
	   && right_type->integer_type()->is_rune())
    *result_type = right_type;
  else
    *result_type = left_type;

  return true;
}

// Convert an integer comparison code and an operator to a boolean
// value.

bool
Binary_expression::cmp_to_bool(Operator op, int cmp)
{
  switch (op)
    {
    case OPERATOR_EQEQ:
      return cmp == 0;
      break;
    case OPERATOR_NOTEQ:
      return cmp != 0;
      break;
    case OPERATOR_LT:
      return cmp < 0;
      break;
    case OPERATOR_LE:
      return cmp <= 0;
    case OPERATOR_GT:
      return cmp > 0;
    case OPERATOR_GE:
      return cmp >= 0;
    default:
      go_unreachable();
    }
}

// Compare constants according to OP.

bool
Binary_expression::compare_constant(Operator op, Numeric_constant* left_nc,
				    Numeric_constant* right_nc,
				    Location location, bool* result)
{
  Type* left_type = left_nc->type();
  Type* right_type = right_nc->type();

  Type* type;
  if (!Binary_expression::operation_type(op, left_type, right_type, &type))
    return false;

  // When comparing an untyped operand to a typed operand, we are
  // effectively coercing the untyped operand to the other operand's
  // type, so make sure that is valid.
  if (!left_nc->set_type(type, true, location)
      || !right_nc->set_type(type, true, location))
    return false;

  bool ret;
  int cmp;
  if (type->complex_type() != NULL)
    {
      if (op != OPERATOR_EQEQ && op != OPERATOR_NOTEQ)
	return false;
      ret = Binary_expression::compare_complex(left_nc, right_nc, &cmp);
    }
  else if (type->float_type() != NULL)
    ret = Binary_expression::compare_float(left_nc, right_nc, &cmp);
  else
    ret = Binary_expression::compare_integer(left_nc, right_nc, &cmp);

  if (ret)
    *result = Binary_expression::cmp_to_bool(op, cmp);

  return ret;
}

// Compare integer constants.

bool
Binary_expression::compare_integer(const Numeric_constant* left_nc,
				   const Numeric_constant* right_nc,
				   int* cmp)
{
  mpz_t left_val;
  if (!left_nc->to_int(&left_val))
    return false;
  mpz_t right_val;
  if (!right_nc->to_int(&right_val))
    {
      mpz_clear(left_val);
      return false;
    }

  *cmp = mpz_cmp(left_val, right_val);

  mpz_clear(left_val);
  mpz_clear(right_val);

  return true;
}

// Compare floating point constants.

bool
Binary_expression::compare_float(const Numeric_constant* left_nc,
				 const Numeric_constant* right_nc,
				 int* cmp)
{
  mpfr_t left_val;
  if (!left_nc->to_float(&left_val))
    return false;
  mpfr_t right_val;
  if (!right_nc->to_float(&right_val))
    {
      mpfr_clear(left_val);
      return false;
    }

  // We already coerced both operands to the same type.  If that type
  // is not an abstract type, we need to round the values accordingly.
  Type* type = left_nc->type();
  if (!type->is_abstract() && type->float_type() != NULL)
    {
      int bits = type->float_type()->bits();
      mpfr_prec_round(left_val, bits, MPFR_RNDN);
      mpfr_prec_round(right_val, bits, MPFR_RNDN);
    }

  *cmp = mpfr_cmp(left_val, right_val);

  mpfr_clear(left_val);
  mpfr_clear(right_val);

  return true;
}

// Compare complex constants.  Complex numbers may only be compared
// for equality.

bool
Binary_expression::compare_complex(const Numeric_constant* left_nc,
				   const Numeric_constant* right_nc,
				   int* cmp)
{
  mpc_t left_val;
  if (!left_nc->to_complex(&left_val))
    return false;
  mpc_t right_val;
  if (!right_nc->to_complex(&right_val))
    {
      mpc_clear(left_val);
      return false;
    }

  // We already coerced both operands to the same type.  If that type
  // is not an abstract type, we need to round the values accordingly.
  Type* type = left_nc->type();
  if (!type->is_abstract() && type->complex_type() != NULL)
    {
      int bits = type->complex_type()->bits();
      mpfr_prec_round(mpc_realref(left_val), bits / 2, MPFR_RNDN);
      mpfr_prec_round(mpc_imagref(left_val), bits / 2, MPFR_RNDN);
      mpfr_prec_round(mpc_realref(right_val), bits / 2, MPFR_RNDN);
      mpfr_prec_round(mpc_imagref(right_val), bits / 2, MPFR_RNDN);
    }

  *cmp = mpc_cmp(left_val, right_val) != 0;

  mpc_clear(left_val);
  mpc_clear(right_val);

  return true;
}

// Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting NC.  Return
// true if this could be done, false if not.  Issue errors at LOCATION
// as appropriate, and sets *ISSUED_ERROR if it did.

bool
Binary_expression::eval_constant(Operator op, Numeric_constant* left_nc,
				 Numeric_constant* right_nc,
				 Location location, Numeric_constant* nc,
				 bool* issued_error)
{
  *issued_error = false;
  switch (op)
    {
    case OPERATOR_OROR:
    case OPERATOR_ANDAND:
    case OPERATOR_EQEQ:
    case OPERATOR_NOTEQ:
    case OPERATOR_LT:
    case OPERATOR_LE:
    case OPERATOR_GT:
    case OPERATOR_GE:
      // These return boolean values, not numeric.
      return false;
    default:
      break;
    }

  Type* left_type = left_nc->type();
  Type* right_type = right_nc->type();

  Type* type;
  if (!Binary_expression::operation_type(op, left_type, right_type, &type))
    return false;

  bool is_shift = op == OPERATOR_LSHIFT || op == OPERATOR_RSHIFT;

  // When combining an untyped operand with a typed operand, we are
  // effectively coercing the untyped operand to the other operand's
  // type, so make sure that is valid.
  if (!left_nc->set_type(type, true, location))
    return false;
  if (!is_shift && !right_nc->set_type(type, true, location))
    return false;
  if (is_shift
      && ((left_type->integer_type() == NULL
           && !left_type->is_abstract())
          || (right_type->integer_type() == NULL
              && !right_type->is_abstract())))
    return false;

  bool r;
  if (type->complex_type() != NULL)
    r = Binary_expression::eval_complex(op, left_nc, right_nc, location, nc);
  else if (type->float_type() != NULL)
    r = Binary_expression::eval_float(op, left_nc, right_nc, location, nc);
  else
    r = Binary_expression::eval_integer(op, left_nc, right_nc, location, nc);

  if (r)
    {
      r = nc->set_type(type, true, location);
      if (!r)
	*issued_error = true;
    }

  return r;
}

// Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting NC, using
// integer operations.  Return true if this could be done, false if
// not.

bool
Binary_expression::eval_integer(Operator op, const Numeric_constant* left_nc,
				const Numeric_constant* right_nc,
				Location location, Numeric_constant* nc)
{
  mpz_t left_val;
  if (!left_nc->to_int(&left_val))
    return false;
  mpz_t right_val;
  if (!right_nc->to_int(&right_val))
    {
      mpz_clear(left_val);
      return false;
    }

  mpz_t val;
  mpz_init(val);

  switch (op)
    {
    case OPERATOR_PLUS:
      mpz_add(val, left_val, right_val);
      if (mpz_sizeinbase(val, 2) > 0x100000)
	{
	  go_error_at(location, "constant addition overflow");
          nc->set_invalid();
	  mpz_set_ui(val, 1);
	}
      break;
    case OPERATOR_MINUS:
      mpz_sub(val, left_val, right_val);
      if (mpz_sizeinbase(val, 2) > 0x100000)
	{
	  go_error_at(location, "constant subtraction overflow");
          nc->set_invalid();
	  mpz_set_ui(val, 1);
	}
      break;
    case OPERATOR_OR:
      mpz_ior(val, left_val, right_val);
      break;
    case OPERATOR_XOR:
      mpz_xor(val, left_val, right_val);
      break;
    case OPERATOR_MULT:
      mpz_mul(val, left_val, right_val);
      if (mpz_sizeinbase(val, 2) > 0x100000)
	{
	  go_error_at(location, "constant multiplication overflow");
          nc->set_invalid();
	  mpz_set_ui(val, 1);
	}
      break;
    case OPERATOR_DIV:
      if (mpz_sgn(right_val) != 0)
	mpz_tdiv_q(val, left_val, right_val);
      else
	{
	  go_error_at(location, "division by zero");
          nc->set_invalid();
	  mpz_set_ui(val, 0);
	}
      break;
    case OPERATOR_MOD:
      if (mpz_sgn(right_val) != 0)
	mpz_tdiv_r(val, left_val, right_val);
      else
	{
	  go_error_at(location, "division by zero");
          nc->set_invalid();
	  mpz_set_ui(val, 0);
	}
      break;
    case OPERATOR_LSHIFT:
      {
	unsigned long shift = mpz_get_ui(right_val);
	if (mpz_cmp_ui(right_val, shift) == 0 && shift <= 0x100000)
	  mpz_mul_2exp(val, left_val, shift);
	else
	  {
	    go_error_at(location, "shift count overflow");
            nc->set_invalid();
	    mpz_set_ui(val, 1);
	  }
	break;
      }
      break;
    case OPERATOR_RSHIFT:
      {
	unsigned long shift = mpz_get_ui(right_val);
	if (mpz_cmp_ui(right_val, shift) != 0)
	  {
	    go_error_at(location, "shift count overflow");
            nc->set_invalid();
	    mpz_set_ui(val, 1);
	  }
	else
	  {
	    if (mpz_cmp_ui(left_val, 0) >= 0)
	      mpz_tdiv_q_2exp(val, left_val, shift);
	    else
	      mpz_fdiv_q_2exp(val, left_val, shift);
	  }
	break;
      }
      break;
    case OPERATOR_AND:
      mpz_and(val, left_val, right_val);
      break;
    case OPERATOR_BITCLEAR:
      {
	mpz_t tval;
	mpz_init(tval);
	mpz_com(tval, right_val);
	mpz_and(val, left_val, tval);
	mpz_clear(tval);
      }
      break;
    default:
      go_unreachable();
    }

  mpz_clear(left_val);
  mpz_clear(right_val);

  if (left_nc->is_rune()
      || (op != OPERATOR_LSHIFT
	  && op != OPERATOR_RSHIFT
	  && right_nc->is_rune()))
    nc->set_rune(NULL, val);
  else
    nc->set_int(NULL, val);

  mpz_clear(val);

  return true;
}

// Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting NC, using
// floating point operations.  Return true if this could be done,
// false if not.

bool
Binary_expression::eval_float(Operator op, const Numeric_constant* left_nc,
			      const Numeric_constant* right_nc,
			      Location location, Numeric_constant* nc)
{
  mpfr_t left_val;
  if (!left_nc->to_float(&left_val))
    return false;
  mpfr_t right_val;
  if (!right_nc->to_float(&right_val))
    {
      mpfr_clear(left_val);
      return false;
    }

  mpfr_t val;
  mpfr_init(val);

  bool ret = true;
  switch (op)
    {
    case OPERATOR_PLUS:
      mpfr_add(val, left_val, right_val, MPFR_RNDN);
      break;
    case OPERATOR_MINUS:
      mpfr_sub(val, left_val, right_val, MPFR_RNDN);
      break;
    case OPERATOR_OR:
    case OPERATOR_XOR:
    case OPERATOR_AND:
    case OPERATOR_BITCLEAR:
    case OPERATOR_MOD:
    case OPERATOR_LSHIFT:
    case OPERATOR_RSHIFT:
      mpfr_set_ui(val, 0, MPFR_RNDN);
      ret = false;
      break;
    case OPERATOR_MULT:
      mpfr_mul(val, left_val, right_val, MPFR_RNDN);
      break;
    case OPERATOR_DIV:
      if (!mpfr_zero_p(right_val))
	mpfr_div(val, left_val, right_val, MPFR_RNDN);
      else
	{
	  go_error_at(location, "division by zero");
          nc->set_invalid();
	  mpfr_set_ui(val, 0, MPFR_RNDN);
	}
      break;
    default:
      go_unreachable();
    }

  mpfr_clear(left_val);
  mpfr_clear(right_val);

  nc->set_float(NULL, val);
  mpfr_clear(val);

  return ret;
}

// Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting NC, using
// complex operations.  Return true if this could be done, false if
// not.

bool
Binary_expression::eval_complex(Operator op, const Numeric_constant* left_nc,
				const Numeric_constant* right_nc,
				Location location, Numeric_constant* nc)
{
  mpc_t left_val;
  if (!left_nc->to_complex(&left_val))
    return false;
  mpc_t right_val;
  if (!right_nc->to_complex(&right_val))
    {
      mpc_clear(left_val);
      return false;
    }

  mpc_t val;
  mpc_init2(val, mpc_precision);

  bool ret = true;
  switch (op)
    {
    case OPERATOR_PLUS:
      mpc_add(val, left_val, right_val, MPC_RNDNN);
      break;
    case OPERATOR_MINUS:
      mpc_sub(val, left_val, right_val, MPC_RNDNN);
      break;
    case OPERATOR_OR:
    case OPERATOR_XOR:
    case OPERATOR_AND:
    case OPERATOR_BITCLEAR:
    case OPERATOR_MOD:
    case OPERATOR_LSHIFT:
    case OPERATOR_RSHIFT:
      mpc_set_ui(val, 0, MPC_RNDNN);
      ret = false;
      break;
    case OPERATOR_MULT:
      mpc_mul(val, left_val, right_val, MPC_RNDNN);
      break;
    case OPERATOR_DIV:
      if (mpc_cmp_si(right_val, 0) == 0)
	{
	  go_error_at(location, "division by zero");
          nc->set_invalid();
	  mpc_set_ui(val, 0, MPC_RNDNN);
	  break;
	}
      mpc_div(val, left_val, right_val, MPC_RNDNN);
      break;
    default:
      go_unreachable();
    }

  mpc_clear(left_val);
  mpc_clear(right_val);

  nc->set_complex(NULL, val);
  mpc_clear(val);

  return ret;
}

// Lower a binary expression.  We have to evaluate constant
// expressions now, in order to implement Go's unlimited precision
// constants.

Expression*
Binary_expression::do_lower(Gogo* gogo, Named_object*,
			    Statement_inserter* inserter, int)
{
  Location location = this->location();
  Operator op = this->op_;
  Expression* left = this->left_;
  Expression* right = this->right_;

  const bool is_comparison = (op == OPERATOR_EQEQ
			      || op == OPERATOR_NOTEQ
			      || op == OPERATOR_LT
			      || op == OPERATOR_LE
			      || op == OPERATOR_GT
			      || op == OPERATOR_GE);

  // Numeric constant expressions.
  {
    Numeric_constant left_nc;
    Numeric_constant right_nc;
    if (left->numeric_constant_value(&left_nc)
	&& right->numeric_constant_value(&right_nc))
      {
	if (is_comparison)
	  {
	    bool result;
	    if (!Binary_expression::compare_constant(op, &left_nc,
						     &right_nc, location,
						     &result))
	      return this;
	    return Expression::make_boolean(result, location);
	  }
	else
	  {
	    Numeric_constant nc;
	    bool issued_error;
	    if (!Binary_expression::eval_constant(op, &left_nc, &right_nc,
						  location, &nc,
						  &issued_error))
	      {
		if (issued_error)
		  return Expression::make_error(location);
                return this;
	      }
	    return nc.expression(location);
	  }
      }
  }

  // String constant expressions.
  //
  // Avoid constant folding here if the left and right types are incompatible
  // (leave the operation intact so that the type checker can complain about it
  // later on). If concatenating an abstract string with a named string type,
  // result type needs to be of the named type (see issue 31412).
  if (left->type()->is_string_type()
      && right->type()->is_string_type()
      && (left->type()->named_type() == NULL
          || right->type()->named_type() == NULL
          || left->type()->named_type() == right->type()->named_type()))
    {
      std::string left_string;
      std::string right_string;
      if (left->string_constant_value(&left_string)
	  && right->string_constant_value(&right_string))
	{
	  if (op == OPERATOR_PLUS)
            {
              Type* result_type = (left->type()->named_type() != NULL
                                   ? left->type()
                                   : right->type());
	      delete left;
	      delete right;
              return Expression::make_string_typed(left_string + right_string,
                                                   result_type, location);
            }
	  else if (is_comparison)
	    {
	      int cmp = left_string.compare(right_string);
	      bool r = Binary_expression::cmp_to_bool(op, cmp);
	      delete left;
	      delete right;
	      return Expression::make_boolean(r, location);
	    }
	}
    }

  // Lower struct, array, and some interface comparisons.
  if (op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ)
    {
      if (left->type()->struct_type() != NULL
	  && right->type()->struct_type() != NULL)
	return this->lower_struct_comparison(gogo, inserter);
      else if (left->type()->array_type() != NULL
	       && !left->type()->is_slice_type()
	       && right->type()->array_type() != NULL
	       && !right->type()->is_slice_type())
	return this->lower_array_comparison(gogo, inserter);
      else if ((left->type()->interface_type() != NULL
                && right->type()->interface_type() == NULL)
               || (left->type()->interface_type() == NULL
                   && right->type()->interface_type() != NULL))
	return this->lower_interface_value_comparison(gogo, inserter);
    }

  // Lower string concatenation to String_concat_expression, so that
  // we can group sequences of string additions.
  if (this->left_->type()->is_string_type() && this->op_ == OPERATOR_PLUS)
    {
      Expression_list* exprs;
      String_concat_expression* left_sce =
	this->left_->string_concat_expression();
      if (left_sce != NULL)
	exprs = left_sce->exprs();
      else
	{
	  exprs = new Expression_list();
	  exprs->push_back(this->left_);
	}

      String_concat_expression* right_sce =
	this->right_->string_concat_expression();
      if (right_sce != NULL)
	exprs->append(right_sce->exprs());
      else
	exprs->push_back(this->right_);

      return Expression::make_string_concat(exprs);
    }

  return this;
}

// Lower a struct comparison.

Expression*
Binary_expression::lower_struct_comparison(Gogo* gogo,
					   Statement_inserter* inserter)
{
  Struct_type* st = this->left_->type()->struct_type();
  Struct_type* st2 = this->right_->type()->struct_type();
  if (st2 == NULL)
    return this;
  if (st != st2
      && !Type::are_identical(st, st2,
			      Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			      NULL))
    return this;
  if (!Type::are_compatible_for_comparison(true, this->left_->type(),
					   this->right_->type(), NULL))
    return this;

  // See if we can compare using memcmp.  As a heuristic, we use
  // memcmp rather than field references and comparisons if there are
  // more than two fields.
  if (st->compare_is_identity(gogo) && st->total_field_count() > 2)
    return this->lower_compare_to_memcmp(gogo, inserter);

  Location loc = this->location();

  Expression* left = this->left_;
  Temporary_statement* left_temp = NULL;
  if (left->var_expression() == NULL
      && left->temporary_reference_expression() == NULL)
    {
      left_temp = Statement::make_temporary(left->type(), NULL, loc);
      inserter->insert(left_temp);
      left = Expression::make_set_and_use_temporary(left_temp, left, loc);
    }

  Expression* right = this->right_;
  Temporary_statement* right_temp = NULL;
  if (right->var_expression() == NULL
      && right->temporary_reference_expression() == NULL)
    {
      right_temp = Statement::make_temporary(right->type(), NULL, loc);
      inserter->insert(right_temp);
      right = Expression::make_set_and_use_temporary(right_temp, right, loc);
    }

  Expression* ret = Expression::make_boolean(true, loc);
  const Struct_field_list* fields = st->fields();
  unsigned int field_index = 0;
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf, ++field_index)
    {
      if (Gogo::is_sink_name(pf->field_name()))
	continue;

      if (field_index > 0)
	{
	  if (left_temp == NULL)
	    left = left->copy();
	  else
	    left = Expression::make_temporary_reference(left_temp, loc);
	  if (right_temp == NULL)
	    right = right->copy();
	  else
	    right = Expression::make_temporary_reference(right_temp, loc);
	}
      Expression* f1 = Expression::make_field_reference(left, field_index,
							loc);
      Expression* f2 = Expression::make_field_reference(right, field_index,
							loc);
      Expression* cond = Expression::make_binary(OPERATOR_EQEQ, f1, f2, loc);
      ret = Expression::make_binary(OPERATOR_ANDAND, ret, cond, loc);
    }

  if (this->op_ == OPERATOR_NOTEQ)
    ret = Expression::make_unary(OPERATOR_NOT, ret, loc);

  return ret;
}

// Lower an array comparison.

Expression*
Binary_expression::lower_array_comparison(Gogo* gogo,
					  Statement_inserter* inserter)
{
  Array_type* at = this->left_->type()->array_type();
  Array_type* at2 = this->right_->type()->array_type();
  if (at2 == NULL)
    return this;
  if (at != at2
      && !Type::are_identical(at, at2,
			      Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			      NULL))
    return this;
  if (!Type::are_compatible_for_comparison(true, this->left_->type(),
					   this->right_->type(), NULL))
    return this;

  // Call memcmp directly if possible.  This may let the middle-end
  // optimize the call.
  if (at->compare_is_identity(gogo))
    return this->lower_compare_to_memcmp(gogo, inserter);

  // Call the array comparison function.
  Named_object* equal_fn =
    at->equal_function(gogo, this->left_->type()->named_type(), NULL);

  Location loc = this->location();

  Expression* func = Expression::make_func_reference(equal_fn, NULL, loc);

  Expression_list* args = new Expression_list();
  args->push_back(this->operand_address(inserter, this->left_));
  args->push_back(this->operand_address(inserter, this->right_));

  Call_expression* ce = Expression::make_call(func, args, false, loc);

  // Record that this is a call to a generated equality function.  We
  // need to do this because a comparison returns an abstract boolean
  // type, but the function necessarily returns "bool".  The
  // difference shows up in code like
  //     type mybool bool
  //     var b mybool = [10]string{} == [10]string{}
  // The comparison function returns "bool", but since a comparison
  // has an abstract boolean type we need an implicit conversion to
  // "mybool".  The implicit conversion is inserted in
  // Call_expression::do_flatten.
  ce->set_is_equal_function();

  Expression* ret = ce;
  if (this->op_ == OPERATOR_NOTEQ)
    ret = Expression::make_unary(OPERATOR_NOT, ret, loc);

  return ret;
}

// Lower an interface to value comparison.

Expression*
Binary_expression::lower_interface_value_comparison(Gogo*,
                                                    Statement_inserter* inserter)
{
  Type* left_type = this->left_->type();
  Type* right_type = this->right_->type();
  Interface_type* ift;
  if (left_type->interface_type() != NULL)
    {
      ift = left_type->interface_type();
      if (!ift->implements_interface(right_type, NULL))
        return this;
    }
  else
    {
      ift = right_type->interface_type();
      if (!ift->implements_interface(left_type, NULL))
        return this;
    }
  if (!Type::are_compatible_for_comparison(true, left_type, right_type, NULL))
    return this;

  Location loc = this->location();

  if (left_type->interface_type() == NULL
      && left_type->points_to() == NULL
      && !this->left_->is_addressable())
    {
      Temporary_statement* temp =
          Statement::make_temporary(left_type, NULL, loc);
      inserter->insert(temp);
      this->left_ =
          Expression::make_set_and_use_temporary(temp, this->left_, loc);
    }

  if (right_type->interface_type() == NULL
      && right_type->points_to() == NULL
      && !this->right_->is_addressable())
    {
      Temporary_statement* temp =
          Statement::make_temporary(right_type, NULL, loc);
      inserter->insert(temp);
      this->right_ =
          Expression::make_set_and_use_temporary(temp, this->right_, loc);
    }

  return this;
}

// Lower a struct or array comparison to a call to memcmp.

Expression*
Binary_expression::lower_compare_to_memcmp(Gogo*, Statement_inserter* inserter)
{
  Location loc = this->location();

  Expression* a1 = this->operand_address(inserter, this->left_);
  Expression* a2 = this->operand_address(inserter, this->right_);
  Expression* len = Expression::make_type_info(this->left_->type(),
					       TYPE_INFO_SIZE);

  Expression* call = Runtime::make_call(Runtime::MEMCMP, loc, 3, a1, a2, len);
  Type* int32_type = Type::lookup_integer_type("int32");
  Expression* zero = Expression::make_integer_ul(0, int32_type, loc);
  return Expression::make_binary(this->op_, call, zero, loc);
}

Expression*
Binary_expression::do_flatten(Gogo* gogo, Named_object*,
                              Statement_inserter* inserter)
{
  Location loc = this->location();
  if (this->left_->type()->is_error_type()
      || this->right_->type()->is_error_type()
      || this->left_->is_error_expression()
      || this->right_->is_error_expression())
    {
      go_assert(saw_errors());
      return Expression::make_error(loc);
    }

  Temporary_statement* temp;

  Type* left_type = this->left_->type();
  bool is_shift_op = (this->op_ == OPERATOR_LSHIFT
                      || this->op_ == OPERATOR_RSHIFT);
  bool is_idiv_op = ((this->op_ == OPERATOR_DIV &&
                      left_type->integer_type() != NULL)
                     || this->op_ == OPERATOR_MOD);
  bool is_string_op = (left_type->is_string_type()
                       && this->right_->type()->is_string_type());

  if (is_string_op)
    {
      // Mark string([]byte) operands to reuse the backing store.
      // String comparison does not keep the reference, so it is safe.
      Type_conversion_expression* lce =
        this->left_->conversion_expression();
      if (lce != NULL && lce->expr()->type()->is_slice_type())
        lce->set_no_copy(true);
      Type_conversion_expression* rce =
        this->right_->conversion_expression();
      if (rce != NULL && rce->expr()->type()->is_slice_type())
        rce->set_no_copy(true);
    }

  if (is_shift_op
      || (is_idiv_op
	  && (gogo->check_divide_by_zero() || gogo->check_divide_overflow()))
      || is_string_op)
    {
      if (!this->left_->is_multi_eval_safe())
        {
          temp = Statement::make_temporary(NULL, this->left_, loc);
          inserter->insert(temp);
          this->left_ = Expression::make_temporary_reference(temp, loc);
        }
      if (!this->right_->is_multi_eval_safe())
        {
          temp =
              Statement::make_temporary(NULL, this->right_, loc);
          this->right_ = Expression::make_temporary_reference(temp, loc);
          inserter->insert(temp);
        }
    }
  return this;
}


// Return the address of EXPR, cast to unsafe.Pointer.

Expression*
Binary_expression::operand_address(Statement_inserter* inserter,
				   Expression* expr)
{
  Location loc = this->location();

  if (!expr->is_addressable())
    {
      Temporary_statement* temp = Statement::make_temporary(expr->type(), NULL,
							    loc);
      inserter->insert(temp);
      expr = Expression::make_set_and_use_temporary(temp, expr, loc);
    }
  expr = Expression::make_unary(OPERATOR_AND, expr, loc);
  static_cast<Unary_expression*>(expr)->set_does_not_escape();
  Type* void_type = Type::make_void_type();
  Type* unsafe_pointer_type = Type::make_pointer_type(void_type);
  return Expression::make_cast(unsafe_pointer_type, expr, loc);
}

// Return the numeric constant value, if it has one.

bool
Binary_expression::do_numeric_constant_value(Numeric_constant* nc) const
{
  Numeric_constant left_nc;
  if (!this->left_->numeric_constant_value(&left_nc))
    return false;
  Numeric_constant right_nc;
  if (!this->right_->numeric_constant_value(&right_nc))
    return false;
  bool issued_error;
  return Binary_expression::eval_constant(this->op_, &left_nc, &right_nc,
					  this->location(), nc, &issued_error);
}

// Return the boolean constant value, if it has one.

bool
Binary_expression::do_boolean_constant_value(bool* val) const
{
  bool is_comparison = false;
  switch (this->op_)
    {
    case OPERATOR_EQEQ:
    case OPERATOR_NOTEQ:
    case OPERATOR_LT:
    case OPERATOR_LE:
    case OPERATOR_GT:
    case OPERATOR_GE:
      is_comparison = true;
      break;
    case OPERATOR_ANDAND:
    case OPERATOR_OROR:
      break;
    default:
      return false;
    }

  Numeric_constant left_nc, right_nc;
  if (is_comparison
      && this->left_->numeric_constant_value(&left_nc)
      && this->right_->numeric_constant_value(&right_nc))
    return Binary_expression::compare_constant(this->op_, &left_nc,
                                               &right_nc,
                                               this->location(),
                                               val);

  std::string left_str, right_str;
  if (is_comparison
      && this->left_->string_constant_value(&left_str)
      && this->right_->string_constant_value(&right_str))
    {
      *val = Binary_expression::cmp_to_bool(this->op_,
                                            left_str.compare(right_str));
      return true;
    }

  bool left_bval;
  if (this->left_->boolean_constant_value(&left_bval))
    {
      if (this->op_ == OPERATOR_ANDAND && !left_bval)
        {
          *val = false;
          return true;
        }
      else if (this->op_ == OPERATOR_OROR && left_bval)
        {
          *val = true;
          return true;
        }

      bool right_bval;
      if (this->right_->boolean_constant_value(&right_bval))
        {
          switch (this->op_)
            {
            case OPERATOR_EQEQ:
              *val = (left_bval == right_bval);
              return true;
            case OPERATOR_NOTEQ:
              *val = (left_bval != right_bval);
              return true;
            case OPERATOR_ANDAND:
            case OPERATOR_OROR:
              *val = right_bval;
              return true;
            default:
              go_unreachable();
            }
        }
    }

  return false;
}

// Note that the value is being discarded.

bool
Binary_expression::do_discarding_value()
{
  if (this->op_ == OPERATOR_OROR || this->op_ == OPERATOR_ANDAND)
    return this->right_->discarding_value();
  else
    {
      this->unused_value_error();
      return false;
    }
}

// Get type.

Type*
Binary_expression::do_type()
{
  if (this->classification() == EXPRESSION_ERROR)
    return Type::make_error_type();

  switch (this->op_)
    {
    case OPERATOR_EQEQ:
    case OPERATOR_NOTEQ:
    case OPERATOR_LT:
    case OPERATOR_LE:
    case OPERATOR_GT:
    case OPERATOR_GE:
      if (this->type_ == NULL)
	this->type_ = Type::make_boolean_type();
      return this->type_;

    case OPERATOR_PLUS:
    case OPERATOR_MINUS:
    case OPERATOR_OR:
    case OPERATOR_XOR:
    case OPERATOR_MULT:
    case OPERATOR_DIV:
    case OPERATOR_MOD:
    case OPERATOR_AND:
    case OPERATOR_BITCLEAR:
    case OPERATOR_OROR:
    case OPERATOR_ANDAND:
      {
	Type* type;
	if (!Binary_expression::operation_type(this->op_,
					       this->left_->type(),
					       this->right_->type(),
					       &type))
	  return Type::make_error_type();
	return type;
      }

    case OPERATOR_LSHIFT:
    case OPERATOR_RSHIFT:
      return this->left_->type();

    default:
      go_unreachable();
    }
}

// Set type for a binary expression.

void
Binary_expression::do_determine_type(const Type_context* context)
{
  Type* tleft = this->left_->type();
  Type* tright = this->right_->type();

  // Both sides should have the same type, except for the shift
  // operations.  For a comparison, we should ignore the incoming
  // type.

  bool is_shift_op = (this->op_ == OPERATOR_LSHIFT
		      || this->op_ == OPERATOR_RSHIFT);

  bool is_comparison = (this->op_ == OPERATOR_EQEQ
			|| this->op_ == OPERATOR_NOTEQ
			|| this->op_ == OPERATOR_LT
			|| this->op_ == OPERATOR_LE
			|| this->op_ == OPERATOR_GT
			|| this->op_ == OPERATOR_GE);

  // For constant expressions, the context of the result is not useful in
  // determining the types of the operands.  It is only legal to use abstract
  // boolean, numeric, and string constants as operands where it is legal to
  // use non-abstract boolean, numeric, and string constants, respectively.
  // Any issues with the operation will be resolved in the check_types pass.
  bool is_constant_expr = (this->left_->is_constant()
                           && this->right_->is_constant());

  Type_context subcontext(*context);

  if (is_constant_expr && !is_shift_op)
    {
      subcontext.type = NULL;
      subcontext.may_be_abstract = true;
    }
  else if (is_comparison)
    {
      // In a comparison, the context does not determine the types of
      // the operands.
      subcontext.type = NULL;
    }

  // Set the context for the left hand operand.
  if (is_shift_op)
    {
      // The right hand operand of a shift plays no role in
      // determining the type of the left hand operand.
    }
  else if (!tleft->is_abstract())
    subcontext.type = tleft;
  else if (!tright->is_abstract())
    subcontext.type = tright;
  else if (subcontext.type == NULL)
    {
      if ((tleft->integer_type() != NULL && tright->integer_type() != NULL)
	  || (tleft->float_type() != NULL && tright->float_type() != NULL)
	  || (tleft->complex_type() != NULL && tright->complex_type() != NULL))
	{
	  // Both sides have an abstract integer, abstract float, or
	  // abstract complex type.  Just let CONTEXT determine
	  // whether they may remain abstract or not.
	}
      else if (tleft->complex_type() != NULL)
	subcontext.type = tleft;
      else if (tright->complex_type() != NULL)
	subcontext.type = tright;
      else if (tleft->float_type() != NULL)
	subcontext.type = tleft;
      else if (tright->float_type() != NULL)
	subcontext.type = tright;
      else
	subcontext.type = tleft;

      if (subcontext.type != NULL && !context->may_be_abstract)
	subcontext.type = subcontext.type->make_non_abstract_type();
    }

  this->left_->determine_type(&subcontext);

  if (is_shift_op)
    {
      // We may have inherited an unusable type for the shift operand.
      // Give a useful error if that happened.
      if (tleft->is_abstract()
	  && subcontext.type != NULL
	  && !subcontext.may_be_abstract
	  && subcontext.type->interface_type() == NULL
	  && subcontext.type->integer_type() == NULL)
	this->report_error(("invalid context-determined non-integer type "
			    "for left operand of shift"));

      // The context for the right hand operand is the same as for the
      // left hand operand, except for a shift operator.
      subcontext.type = Type::lookup_integer_type("uint");
      subcontext.may_be_abstract = false;
    }

  this->right_->determine_type(&subcontext);

  if (is_comparison)
    {
      if (this->type_ != NULL && !this->type_->is_abstract())
	;
      else if (context->type != NULL && context->type->is_boolean_type())
	this->type_ = context->type;
      else if (!context->may_be_abstract)
	this->type_ = Type::lookup_bool_type();
    }
}

// Report an error if the binary operator OP does not support TYPE.
// OTYPE is the type of the other operand.  Return whether the
// operation is OK.  This should not be used for shift.

bool
Binary_expression::check_operator_type(Operator op, Type* type, Type* otype,
				       Location location)
{
  switch (op)
    {
    case OPERATOR_OROR:
    case OPERATOR_ANDAND:
      if (!type->is_boolean_type()
          || !otype->is_boolean_type())
	{
	  go_error_at(location, "expected boolean type");
	  return false;
	}
      break;

    case OPERATOR_EQEQ:
    case OPERATOR_NOTEQ:
      {
	std::string reason;
	if (!Type::are_compatible_for_comparison(true, type, otype, &reason))
	  {
	    go_error_at(location, "%s", reason.c_str());
	    return false;
	  }
      }
      break;

    case OPERATOR_LT:
    case OPERATOR_LE:
    case OPERATOR_GT:
    case OPERATOR_GE:
      {
	std::string reason;
	if (!Type::are_compatible_for_comparison(false, type, otype, &reason))
	  {
	    go_error_at(location, "%s", reason.c_str());
	    return false;
	  }
      }
      break;

    case OPERATOR_PLUS:
    case OPERATOR_PLUSEQ:
      if ((!type->is_numeric_type() && !type->is_string_type())
          || (!otype->is_numeric_type() && !otype->is_string_type()))
	{
	  go_error_at(location,
		   "expected integer, floating, complex, or string type");
	  return false;
	}
      break;

    case OPERATOR_MINUS:
    case OPERATOR_MINUSEQ:
    case OPERATOR_MULT:
    case OPERATOR_MULTEQ:
    case OPERATOR_DIV:
    case OPERATOR_DIVEQ:
      if (!type->is_numeric_type() || !otype->is_numeric_type())
	{
	  go_error_at(location, "expected integer, floating, or complex type");
	  return false;
	}
      break;

    case OPERATOR_MOD:
    case OPERATOR_MODEQ:
    case OPERATOR_OR:
    case OPERATOR_OREQ:
    case OPERATOR_AND:
    case OPERATOR_ANDEQ:
    case OPERATOR_XOR:
    case OPERATOR_XOREQ:
    case OPERATOR_BITCLEAR:
    case OPERATOR_BITCLEAREQ:
      if (type->integer_type() == NULL || otype->integer_type() == NULL)
	{
	  go_error_at(location, "expected integer type");
	  return false;
	}
      break;

    default:
      go_unreachable();
    }

  return true;
}

// Check types.

void
Binary_expression::do_check_types(Gogo*)
{
  if (this->classification() == EXPRESSION_ERROR)
    return;

  Type* left_type = this->left_->type();
  Type* right_type = this->right_->type();
  if (left_type->is_error() || right_type->is_error())
    {
      this->set_is_error();
      return;
    }

  if (this->op_ == OPERATOR_EQEQ
      || this->op_ == OPERATOR_NOTEQ
      || this->op_ == OPERATOR_LT
      || this->op_ == OPERATOR_LE
      || this->op_ == OPERATOR_GT
      || this->op_ == OPERATOR_GE)
    {
      if (left_type->is_nil_type() && right_type->is_nil_type())
	{
	  this->report_error(_("invalid comparison of nil with nil"));
	  return;
	}
      if (!Type::are_assignable(left_type, right_type, NULL)
	  && !Type::are_assignable(right_type, left_type, NULL))
	{
	  this->report_error(_("incompatible types in binary expression"));
	  return;
	}
      if (!Binary_expression::check_operator_type(this->op_, left_type,
						  right_type,
						  this->location())
	  || !Binary_expression::check_operator_type(this->op_, right_type,
						     left_type,
						     this->location()))
	{
	  this->set_is_error();
	  return;
	}
    }
  else if (this->op_ != OPERATOR_LSHIFT && this->op_ != OPERATOR_RSHIFT)
    {
      if (!Type::are_compatible_for_binop(left_type, right_type))
	{
	  this->report_error(_("incompatible types in binary expression"));
	  return;
	}
      if (!Binary_expression::check_operator_type(this->op_, left_type,
						  right_type,
						  this->location()))
	{
	  this->set_is_error();
	  return;
	}
      if (this->op_ == OPERATOR_DIV || this->op_ == OPERATOR_MOD)
	{
	  // Division by a zero integer constant is an error.
	  Numeric_constant rconst;
	  unsigned long rval;
	  if (left_type->integer_type() != NULL
	      && this->right_->numeric_constant_value(&rconst)
	      && rconst.to_unsigned_long(&rval) == Numeric_constant::NC_UL_VALID
	      && rval == 0)
	    {
	      this->report_error(_("integer division by zero"));
	      return;
	    }
	}
    }
  else
    {
      if (left_type->integer_type() == NULL)
	this->report_error(_("shift of non-integer operand"));

      if (right_type->is_string_type())
        this->report_error(_("shift count not integer"));
      else if (!right_type->is_abstract()
	       && right_type->integer_type() == NULL)
	this->report_error(_("shift count not integer"));
      else
	{
	  Numeric_constant nc;
	  if (this->right_->numeric_constant_value(&nc))
	    {
	      mpz_t val;
	      if (!nc.to_int(&val))
		this->report_error(_("shift count not integer"));
	      else
		{
		  if (mpz_sgn(val) < 0)
		    {
		      this->report_error(_("negative shift count"));
		      Location rloc = this->right_->location();
		      this->right_ = Expression::make_integer_ul(0, right_type,
								 rloc);
		    }
		  mpz_clear(val);
		}
	    }
	}
    }
}

// Get the backend representation for a binary expression.

Bexpression*
Binary_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Location loc = this->location();
  Type* left_type = this->left_->type();
  Type* right_type = this->right_->type();

  bool use_left_type = true;
  bool is_shift_op = false;
  bool is_idiv_op = false;
  switch (this->op_)
    {
    case OPERATOR_EQEQ:
    case OPERATOR_NOTEQ:
    case OPERATOR_LT:
    case OPERATOR_LE:
    case OPERATOR_GT:
    case OPERATOR_GE:
      return Expression::comparison(context, this->type_, this->op_,
				    this->left_, this->right_, loc);

    case OPERATOR_OROR:
    case OPERATOR_ANDAND:
      use_left_type = false;
      break;
    case OPERATOR_PLUS:
    case OPERATOR_MINUS:
    case OPERATOR_OR:
    case OPERATOR_XOR:
    case OPERATOR_MULT:
      break;
    case OPERATOR_DIV:
      if (left_type->float_type() != NULL || left_type->complex_type() != NULL)
        break;
      // Fall through.
    case OPERATOR_MOD:
      is_idiv_op = true;
      break;
    case OPERATOR_LSHIFT:
    case OPERATOR_RSHIFT:
      is_shift_op = true;
      break;
    case OPERATOR_BITCLEAR:
      this->right_ = Expression::make_unary(OPERATOR_XOR, this->right_, loc);
    case OPERATOR_AND:
      break;
    default:
      go_unreachable();
    }

  // The only binary operation for string is +, and that should have
  // been converted to a String_concat_expression in do_lower.
  go_assert(!left_type->is_string_type());

  Bexpression* left = this->left_->get_backend(context);
  Bexpression* right = this->right_->get_backend(context);

  Type* type = use_left_type ? left_type : right_type;
  Btype* btype = type->get_backend(gogo);

  Bexpression* ret =
      gogo->backend()->binary_expression(this->op_, left, right, loc);
  ret = gogo->backend()->convert_expression(btype, ret, loc);

  // Initialize overflow constants.
  Bexpression* overflow;
  mpz_t zero;
  mpz_init_set_ui(zero, 0UL);
  mpz_t one;
  mpz_init_set_ui(one, 1UL);
  mpz_t neg_one;
  mpz_init_set_si(neg_one, -1);

  Btype* left_btype = left_type->get_backend(gogo);
  Btype* right_btype = right_type->get_backend(gogo);

  // In Go, a shift larger than the size of the type is well-defined.
  // This is not true in C, so we need to insert a conditional.
  // We also need to check for a negative shift count.
  if (is_shift_op)
    {
      go_assert(left_type->integer_type() != NULL);
      go_assert(right_type->integer_type() != NULL);

      int bits = left_type->integer_type()->bits();

      Numeric_constant nc;
      unsigned long ul;
      if (!this->right_->numeric_constant_value(&nc)
	  || nc.to_unsigned_long(&ul) != Numeric_constant::NC_UL_VALID
	  || ul >= static_cast<unsigned long>(bits))
	{
	  mpz_t bitsval;
	  mpz_init_set_ui(bitsval, bits);
	  Bexpression* bits_expr =
	    gogo->backend()->integer_constant_expression(right_btype, bitsval);
	  Bexpression* compare =
	    gogo->backend()->binary_expression(OPERATOR_LT,
					       right, bits_expr, loc);

	  Bexpression* zero_expr =
	    gogo->backend()->integer_constant_expression(left_btype, zero);
	  overflow = zero_expr;
	  Bfunction* bfn = context->function()->func_value()->get_decl();
	  if (this->op_ == OPERATOR_RSHIFT
	      && !left_type->integer_type()->is_unsigned())
	    {
	      Bexpression* neg_expr =
		gogo->backend()->binary_expression(OPERATOR_LT, left,
						   zero_expr, loc);
	      Bexpression* neg_one_expr =
		gogo->backend()->integer_constant_expression(left_btype,
							     neg_one);
	      overflow = gogo->backend()->conditional_expression(bfn,
								 btype,
								 neg_expr,
								 neg_one_expr,
								 zero_expr,
								 loc);
	    }
	  ret = gogo->backend()->conditional_expression(bfn, btype, compare,
							ret, overflow, loc);
	  mpz_clear(bitsval);
	}

      if (!right_type->integer_type()->is_unsigned()
	  && (!this->right_->numeric_constant_value(&nc)
	      || nc.to_unsigned_long(&ul) != Numeric_constant::NC_UL_VALID))
	{
	  Bexpression* zero_expr =
	    gogo->backend()->integer_constant_expression(right_btype, zero);
	  Bexpression* compare =
	    gogo->backend()->binary_expression(OPERATOR_LT, right, zero_expr,
					       loc);
	  Expression* crash = Runtime::make_call(Runtime::PANIC_SHIFT,
						 loc, 0);
	  Bexpression* bcrash = crash->get_backend(context);
	  Bfunction* bfn = context->function()->func_value()->get_decl();
	  ret = gogo->backend()->conditional_expression(bfn, btype, compare,
							bcrash, ret, loc);
	}
    }

  // Add checks for division by zero and division overflow as needed.
  if (is_idiv_op)
    {
      if (gogo->check_divide_by_zero())
	{
	  // right == 0
          Bexpression* zero_expr =
              gogo->backend()->integer_constant_expression(right_btype, zero);
          Bexpression* check =
              gogo->backend()->binary_expression(OPERATOR_EQEQ,
                                                 right, zero_expr, loc);

	  Expression* crash = Runtime::make_call(Runtime::PANIC_DIVIDE,
						 loc, 0);
	  Bexpression* bcrash = crash->get_backend(context);

	  // right == 0 ? (panicdivide(), 0) : ret
          Bfunction* bfn = context->function()->func_value()->get_decl();
          ret = gogo->backend()->conditional_expression(bfn, btype,
                                                        check, bcrash,
							ret, loc);
	}

      if (gogo->check_divide_overflow())
	{
	  // right == -1
	  // FIXME: It would be nice to say that this test is expected
	  // to return false.

          Bexpression* neg_one_expr =
              gogo->backend()->integer_constant_expression(right_btype, neg_one);
          Bexpression* check =
              gogo->backend()->binary_expression(OPERATOR_EQEQ,
                                                 right, neg_one_expr, loc);

          Bexpression* zero_expr =
              gogo->backend()->integer_constant_expression(btype, zero);
          Bexpression* one_expr =
              gogo->backend()->integer_constant_expression(btype, one);
          Bfunction* bfn = context->function()->func_value()->get_decl();

	  if (type->integer_type()->is_unsigned())
	    {
	      // An unsigned -1 is the largest possible number, so
	      // dividing is always 1 or 0.

              Bexpression* cmp =
                  gogo->backend()->binary_expression(OPERATOR_EQEQ,
                                                     left, right, loc);
	      if (this->op_ == OPERATOR_DIV)
                overflow =
                    gogo->backend()->conditional_expression(bfn, btype, cmp,
                                                            one_expr, zero_expr,
                                                            loc);
	      else
                overflow =
                    gogo->backend()->conditional_expression(bfn, btype, cmp,
                                                            zero_expr, left,
                                                            loc);
	    }
	  else
	    {
	      // Computing left / -1 is the same as computing - left,
	      // which does not overflow since Go sets -fwrapv.
	      if (this->op_ == OPERATOR_DIV)
                {
                  Expression* negate_expr =
                      Expression::make_unary(OPERATOR_MINUS, this->left_, loc);
                  overflow = negate_expr->get_backend(context);
                }
	      else
                overflow = zero_expr;
	    }
          overflow = gogo->backend()->convert_expression(btype, overflow, loc);

	  // right == -1 ? - left : ret
          ret = gogo->backend()->conditional_expression(bfn, btype,
                                                        check, overflow,
                                                        ret, loc);
	}
    }

  mpz_clear(zero);
  mpz_clear(one);
  mpz_clear(neg_one);
  return ret;
}

// Export a binary expression.

void
Binary_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("(");
  this->left_->export_expression(efb);
  switch (this->op_)
    {
    case OPERATOR_OROR:
      efb->write_c_string(" || ");
      break;
    case OPERATOR_ANDAND:
      efb->write_c_string(" && ");
      break;
    case OPERATOR_EQEQ:
      efb->write_c_string(" == ");
      break;
    case OPERATOR_NOTEQ:
      efb->write_c_string(" != ");
      break;
    case OPERATOR_LT:
      efb->write_c_string(" < ");
      break;
    case OPERATOR_LE:
      efb->write_c_string(" <= ");
      break;
    case OPERATOR_GT:
      efb->write_c_string(" > ");
      break;
    case OPERATOR_GE:
      efb->write_c_string(" >= ");
      break;
    case OPERATOR_PLUS:
      efb->write_c_string(" + ");
      break;
    case OPERATOR_MINUS:
      efb->write_c_string(" - ");
      break;
    case OPERATOR_OR:
      efb->write_c_string(" | ");
      break;
    case OPERATOR_XOR:
      efb->write_c_string(" ^ ");
      break;
    case OPERATOR_MULT:
      efb->write_c_string(" * ");
      break;
    case OPERATOR_DIV:
      efb->write_c_string(" / ");
      break;
    case OPERATOR_MOD:
      efb->write_c_string(" % ");
      break;
    case OPERATOR_LSHIFT:
      efb->write_c_string(" << ");
      break;
    case OPERATOR_RSHIFT:
      efb->write_c_string(" >> ");
      break;
    case OPERATOR_AND:
      efb->write_c_string(" & ");
      break;
    case OPERATOR_BITCLEAR:
      efb->write_c_string(" &^ ");
      break;
    default:
      go_unreachable();
    }
  this->right_->export_expression(efb);
  efb->write_c_string(")");
}

// Import a binary expression.

Expression*
Binary_expression::do_import(Import_expression* imp, Location loc)
{
  imp->require_c_string("(");

  Expression* left = Expression::import_expression(imp, loc);

  Operator op;
  if (imp->match_c_string(" || "))
    {
      op = OPERATOR_OROR;
      imp->advance(4);
    }
  else if (imp->match_c_string(" && "))
    {
      op = OPERATOR_ANDAND;
      imp->advance(4);
    }
  else if (imp->match_c_string(" == "))
    {
      op = OPERATOR_EQEQ;
      imp->advance(4);
    }
  else if (imp->match_c_string(" != "))
    {
      op = OPERATOR_NOTEQ;
      imp->advance(4);
    }
  else if (imp->match_c_string(" < "))
    {
      op = OPERATOR_LT;
      imp->advance(3);
    }
  else if (imp->match_c_string(" <= "))
    {
      op = OPERATOR_LE;
      imp->advance(4);
    }
  else if (imp->match_c_string(" > "))
    {
      op = OPERATOR_GT;
      imp->advance(3);
    }
  else if (imp->match_c_string(" >= "))
    {
      op = OPERATOR_GE;
      imp->advance(4);
    }
  else if (imp->match_c_string(" + "))
    {
      op = OPERATOR_PLUS;
      imp->advance(3);
    }
  else if (imp->match_c_string(" - "))
    {
      op = OPERATOR_MINUS;
      imp->advance(3);
    }
  else if (imp->match_c_string(" | "))
    {
      op = OPERATOR_OR;
      imp->advance(3);
    }
  else if (imp->match_c_string(" ^ "))
    {
      op = OPERATOR_XOR;
      imp->advance(3);
    }
  else if (imp->match_c_string(" * "))
    {
      op = OPERATOR_MULT;
      imp->advance(3);
    }
  else if (imp->match_c_string(" / "))
    {
      op = OPERATOR_DIV;
      imp->advance(3);
    }
  else if (imp->match_c_string(" % "))
    {
      op = OPERATOR_MOD;
      imp->advance(3);
    }
  else if (imp->match_c_string(" << "))
    {
      op = OPERATOR_LSHIFT;
      imp->advance(4);
    }
  else if (imp->match_c_string(" >> "))
    {
      op = OPERATOR_RSHIFT;
      imp->advance(4);
    }
  else if (imp->match_c_string(" & "))
    {
      op = OPERATOR_AND;
      imp->advance(3);
    }
  else if (imp->match_c_string(" &^ "))
    {
      op = OPERATOR_BITCLEAR;
      imp->advance(4);
    }
  else if (imp->match_c_string(")"))
    {
      // Not a binary operator after all.
      imp->advance(1);
      return left;
    }
  else
    {
      go_error_at(imp->location(), "unrecognized binary operator");
      return Expression::make_error(loc);
    }

  Expression* right = Expression::import_expression(imp, loc);

  imp->require_c_string(")");

  return Expression::make_binary(op, left, right, loc);
}

// Dump ast representation of a binary expression.

void
Binary_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "(";
  ast_dump_context->dump_expression(this->left_);
  ast_dump_context->ostream() << " ";
  ast_dump_context->dump_operator(this->op_);
  ast_dump_context->ostream() << " ";
  ast_dump_context->dump_expression(this->right_);
  ast_dump_context->ostream() << ") ";
}

// Make a binary expression.

Expression*
Expression::make_binary(Operator op, Expression* left, Expression* right,
			Location location)
{
  return new Binary_expression(op, left, right, location);
}

// Implement a comparison.

Bexpression*
Expression::comparison(Translate_context* context, Type* result_type,
		       Operator op, Expression* left, Expression* right,
		       Location location)
{
  Type* left_type = left->type();
  Type* right_type = right->type();

  Expression* zexpr = Expression::make_integer_ul(0, NULL, location);

  if (left_type->is_string_type() && right_type->is_string_type())
    {
      go_assert(left->is_multi_eval_safe());
      go_assert(right->is_multi_eval_safe());

      if (op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ)
	{
          // (l.len == r.len
          //  ? (l.ptr == r.ptr ? true : memcmp(l.ptr, r.ptr, r.len) == 0)
          //  : false)
          Expression* llen = Expression::make_string_info(left,
                                                          STRING_INFO_LENGTH,
                                                          location);
          Expression* rlen = Expression::make_string_info(right,
                                                          STRING_INFO_LENGTH,
                                                          location);
          Expression* leneq = Expression::make_binary(OPERATOR_EQEQ, llen, rlen,
                                                      location);
          Expression* lptr = Expression::make_string_info(left->copy(),
                                                          STRING_INFO_DATA,
                                                          location);
          Expression* rptr = Expression::make_string_info(right->copy(),
                                                          STRING_INFO_DATA,
                                                          location);
          Expression* ptreq = Expression::make_binary(OPERATOR_EQEQ, lptr, rptr,
                                                      location);
          Expression* btrue = Expression::make_boolean(true, location);
          Expression* call = Runtime::make_call(Runtime::MEMCMP, location, 3,
                                                lptr->copy(), rptr->copy(),
                                                rlen->copy());
          Type* int32_type = Type::lookup_integer_type("int32");
          Expression* zero = Expression::make_integer_ul(0, int32_type, location);
          Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, call, zero,
                                                    location);
          Expression* cond = Expression::make_conditional(ptreq, btrue, cmp,
                                                          location);
          Expression* bfalse = Expression::make_boolean(false, location);
          left = Expression::make_conditional(leneq, cond, bfalse, location);
	  right = Expression::make_boolean(true, location);
	}
      else
	{
	  left = Runtime::make_call(Runtime::CMPSTRING, location, 2,
				    left, right);
	  right = zexpr;
	}
    }
  else if ((left_type->interface_type() != NULL
	    && right_type->interface_type() == NULL
	    && !right_type->is_nil_type())
	   || (left_type->interface_type() == NULL
	       && !left_type->is_nil_type()
	       && right_type->interface_type() != NULL))
    {
      // Comparing an interface value to a non-interface value.
      if (left_type->interface_type() == NULL)
	{
	  std::swap(left_type, right_type);
	  std::swap(left, right);
	}

      // The right operand is not an interface.  We need to take its
      // address if it is not a direct interface type.
      Expression* pointer_arg = NULL;
      if (right_type->is_direct_iface_type())
        pointer_arg = Expression::unpack_direct_iface(right, location);
      else
	{
          go_assert(right->is_addressable());
          pointer_arg = Expression::make_unary(OPERATOR_AND, right,
                                               location);
	}

      Expression* descriptor =
          Expression::make_type_descriptor(right_type, location);
      left =
          Runtime::make_call((left_type->interface_type()->is_empty()
                              ? Runtime::EFACEVALEQ
                              : Runtime::IFACEVALEQ),
                             location, 3, left, descriptor,
                             pointer_arg);
      go_assert(op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ);
      right = Expression::make_boolean(true, location);
    }
  else if (left_type->interface_type() != NULL
	   && right_type->interface_type() != NULL)
    {
      Runtime::Function compare_function;
      if (left_type->interface_type()->is_empty()
	  && right_type->interface_type()->is_empty())
	compare_function = Runtime::EFACEEQ;
      else if (!left_type->interface_type()->is_empty()
	       && !right_type->interface_type()->is_empty())
	compare_function = Runtime::IFACEEQ;
      else
	{
	  if (left_type->interface_type()->is_empty())
	    {
	      std::swap(left_type, right_type);
	      std::swap(left, right);
	    }
	  go_assert(!left_type->interface_type()->is_empty());
	  go_assert(right_type->interface_type()->is_empty());
	  compare_function = Runtime::IFACEEFACEEQ;
	}

      left = Runtime::make_call(compare_function, location, 2, left, right);
      go_assert(op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ);
      right = Expression::make_boolean(true, location);
    }

  if (left_type->is_nil_type()
      && (op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ))
    {
      std::swap(left_type, right_type);
      std::swap(left, right);
    }

  if (right_type->is_nil_type())
    {
      right = Expression::make_nil(location);
      if (left_type->array_type() != NULL
	  && left_type->array_type()->length() == NULL)
	{
	  Array_type* at = left_type->array_type();
          bool is_lvalue = false;
          left = at->get_value_pointer(context->gogo(), left, is_lvalue);
	}
      else if (left_type->interface_type() != NULL)
	{
	  // An interface is nil if the first field is nil.
          left = Expression::make_field_reference(left, 0, location);
	}
    }

  Bexpression* left_bexpr = left->get_backend(context);
  Bexpression* right_bexpr = right->get_backend(context);

  Gogo* gogo = context->gogo();
  Bexpression* ret = gogo->backend()->binary_expression(op, left_bexpr,
                                                        right_bexpr, location);
  if (result_type != NULL)
    ret = gogo->backend()->convert_expression(result_type->get_backend(gogo),
                                              ret, location);
  return ret;
}

// Class String_concat_expression.

bool
String_concat_expression::do_is_constant() const
{
  for (Expression_list::const_iterator pe = this->exprs_->begin();
       pe != this->exprs_->end();
       ++pe)
    {
      if (!(*pe)->is_constant())
	return false;
    }
  return true;
}

bool
String_concat_expression::do_is_zero_value() const
{
  for (Expression_list::const_iterator pe = this->exprs_->begin();
       pe != this->exprs_->end();
       ++pe)
    {
      if (!(*pe)->is_zero_value())
	return false;
    }
  return true;
}

bool
String_concat_expression::do_is_static_initializer() const
{
  for (Expression_list::const_iterator pe = this->exprs_->begin();
       pe != this->exprs_->end();
       ++pe)
    {
      if (!(*pe)->is_static_initializer())
	return false;
    }
  return true;
}

Type*
String_concat_expression::do_type()
{
  Type* t = this->exprs_->front()->type();
  Expression_list::iterator pe = this->exprs_->begin();
  ++pe;
  for (; pe != this->exprs_->end(); ++pe)
    {
      Type* t1;
      if (!Binary_expression::operation_type(OPERATOR_PLUS, t,
					     (*pe)->type(),
					     &t1))
	return Type::make_error_type();
      t = t1;
    }
  return t;
}

void
String_concat_expression::do_determine_type(const Type_context* context)
{
  Type_context subcontext(*context);
  for (Expression_list::iterator pe = this->exprs_->begin();
       pe != this->exprs_->end();
       ++pe)
    {
      Type* t = (*pe)->type();
      if (!t->is_abstract())
	{
	  subcontext.type = t;
	  break;
	}
    }
  if (subcontext.type == NULL)
    subcontext.type = this->exprs_->front()->type();
  for (Expression_list::iterator pe = this->exprs_->begin();
       pe != this->exprs_->end();
       ++pe)
    (*pe)->determine_type(&subcontext);
}

void
String_concat_expression::do_check_types(Gogo*)
{
  if (this->is_error_expression())
    return;
  Type* t = this->exprs_->front()->type();
  if (t->is_error())
    {
      this->set_is_error();
      return;
    }
  Expression_list::iterator pe = this->exprs_->begin();
  ++pe;
  for (; pe != this->exprs_->end(); ++pe)
    {
      Type* t1 = (*pe)->type();
      if (!Type::are_compatible_for_binop(t, t1))
	{
	  this->report_error("incompatible types in binary expression");
	  return;
	}
      if (!Binary_expression::check_operator_type(OPERATOR_PLUS, t, t1,
						  this->location()))
	{
	  this->set_is_error();
	  return;
	}
    }
}

Expression*
String_concat_expression::do_flatten(Gogo*, Named_object*,
				     Statement_inserter* inserter)
{
  if (this->is_error_expression())
    return this;
  Location loc = this->location();
  Type* type = this->type();

  // Mark string([]byte) operands to reuse the backing store.
  // runtime.concatstrings does not keep the reference.
  //
  // Note: in the gc runtime, if all but one inputs are empty,
  // concatstrings returns the only nonempty input without copy.
  // So it is not safe to reuse the backing store if it is a
  // string([]byte) conversion. So the gc compiler does the
  // no-copy optimization only when there is at least one
  // constant nonempty input. Currently the gccgo runtime
  // doesn't do this, so we don't do the check.
  for (Expression_list::iterator p = this->exprs_->begin();
       p != this->exprs_->end();
       ++p)
    {
      Type_conversion_expression* tce = (*p)->conversion_expression();
      if (tce != NULL)
        tce->set_no_copy(true);
    }

  Expression* buf = NULL;
  Node* n = Node::make_node(this);
  if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
    {
      size_t size = 0;
      for (Expression_list::iterator p = this->exprs_->begin();
           p != this->exprs_->end();
           ++p)
        {
          std::string s;
          if ((*p)->string_constant_value(&s))
            size += s.length();
        }
      // Make a buffer on stack if the result does not escape.
      // But don't do this if we know it won't fit.
      if (size < (size_t)tmp_string_buf_size)
        {
          Type* byte_type = Type::lookup_integer_type("uint8");
          Expression* buflen =
            Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
          Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
          Type* array_type = Type::make_array_type(byte_type, buflen);
          buf = Expression::make_allocation(array_type, loc);
          buf->allocation_expression()->set_allocate_on_stack();
          buf->allocation_expression()->set_no_zero();
        }
    }
  if (buf == NULL)
    buf = Expression::make_nil(loc);
  go_assert(this->exprs_->size() > 1);
  Expression* len =
    Expression::make_integer_ul(this->exprs_->size(), NULL, loc);
  Array_type* array_type = Type::make_array_type(type, len);
  array_type->set_is_array_incomparable();
  Expression* array =
    Expression::make_array_composite_literal(array_type, this->exprs_,
                                             loc);
  Temporary_statement* ts =
    Statement::make_temporary(array_type, array, loc);
  inserter->insert(ts);
  Expression* ref = Expression::make_temporary_reference(ts, loc);
  ref = Expression::make_unary(OPERATOR_AND, ref, loc);
	Expression* call =
    Runtime::make_call(Runtime::CONCATSTRINGS, loc, 3, buf,
                       ref, len->copy());
  return Expression::make_cast(type, call, loc);
}

void
String_concat_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "concat(";
  ast_dump_context->dump_expression_list(this->exprs_, false);
  ast_dump_context->ostream() << ")";
}

Expression*
Expression::make_string_concat(Expression_list* exprs)
{
  return new String_concat_expression(exprs);
}

// Class Bound_method_expression.

// Traversal.

int
Bound_method_expression::do_traverse(Traverse* traverse)
{
  return Expression::traverse(&this->expr_, traverse);
}

// Return the type of a bound method expression.  The type of this
// object is simply the type of the method with no receiver.

Type*
Bound_method_expression::do_type()
{
  Named_object* fn = this->method_->named_object();
  Function_type* fntype;
  if (fn->is_function())
    fntype = fn->func_value()->type();
  else if (fn->is_function_declaration())
    fntype = fn->func_declaration_value()->type();
  else
    return Type::make_error_type();
  return fntype->copy_without_receiver();
}

// Determine the types of a method expression.

void
Bound_method_expression::do_determine_type(const Type_context*)
{
  Named_object* fn = this->method_->named_object();
  Function_type* fntype;
  if (fn->is_function())
    fntype = fn->func_value()->type();
  else if (fn->is_function_declaration())
    fntype = fn->func_declaration_value()->type();
  else
    fntype = NULL;
  if (fntype == NULL || !fntype->is_method())
    this->expr_->determine_type_no_context();
  else
    {
      Type_context subcontext(fntype->receiver()->type(), false);
      this->expr_->determine_type(&subcontext);
    }
}

// Check the types of a method expression.

void
Bound_method_expression::do_check_types(Gogo*)
{
  Named_object* fn = this->method_->named_object();
  if (!fn->is_function() && !fn->is_function_declaration())
    {
      this->report_error(_("object is not a method"));
      return;
    }

  Function_type* fntype;
  if (fn->is_function())
    fntype = fn->func_value()->type();
  else if (fn->is_function_declaration())
    fntype = fn->func_declaration_value()->type();
  else
    go_unreachable();
  Type* rtype = fntype->receiver()->type()->deref();
  Type* etype = (this->expr_type_ != NULL
		 ? this->expr_type_
		 : this->expr_->type());
  etype = etype->deref();
  if (!Type::are_identical(rtype, etype, Type::COMPARE_TAGS, NULL))
    this->report_error(_("method type does not match object type"));
}

// If a bound method expression is not simply called, then it is
// represented as a closure.  The closure will hold a single variable,
// the receiver to pass to the method.  The function will be a simple
// thunk that pulls that value from the closure and calls the method
// with the remaining arguments.
//
// Because method values are not common, we don't build all thunks for
// every methods, but instead only build them as we need them.  In
// particular, we even build them on demand for methods defined in
// other packages.

Bound_method_expression::Method_value_thunks
  Bound_method_expression::method_value_thunks;

// Find or create the thunk for METHOD.

Named_object*
Bound_method_expression::create_thunk(Gogo* gogo, const Method* method,
				      Named_object* fn)
{
  std::pair<Named_object*, Named_object*> val(fn, NULL);
  std::pair<Method_value_thunks::iterator, bool> ins =
    Bound_method_expression::method_value_thunks.insert(val);
  if (!ins.second)
    {
      // We have seen this method before.
      go_assert(ins.first->second != NULL);
      return ins.first->second;
    }

  Location loc = fn->location();

  Function_type* orig_fntype;
  if (fn->is_function())
    orig_fntype = fn->func_value()->type();
  else if (fn->is_function_declaration())
    orig_fntype = fn->func_declaration_value()->type();
  else
    orig_fntype = NULL;

  if (orig_fntype == NULL || !orig_fntype->is_method())
    {
      ins.first->second =
	Named_object::make_erroneous_name(gogo->thunk_name());
      return ins.first->second;
    }

  Struct_field_list* sfl = new Struct_field_list();
  // The type here is wrong--it should be the C function type.  But it
  // doesn't really matter.
  Type* vt = Type::make_pointer_type(Type::make_void_type());
  sfl->push_back(Struct_field(Typed_identifier("fn", vt, loc)));
  sfl->push_back(Struct_field(Typed_identifier("val",
					       orig_fntype->receiver()->type(),
					       loc)));
  Struct_type* st = Type::make_struct_type(sfl, loc);
  st->set_is_struct_incomparable();
  Type* closure_type = Type::make_pointer_type(st);

  Function_type* new_fntype = orig_fntype->copy_with_names();

  std::string thunk_name = gogo->thunk_name();
  Named_object* new_no = gogo->start_function(thunk_name, new_fntype,
					      false, loc);

  Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc);
  cvar->set_is_used();
  cvar->set_is_closure();
  Named_object* cp = Named_object::make_variable("$closure" + thunk_name,
						 NULL, cvar);
  new_no->func_value()->set_closure_var(cp);

  gogo->start_block(loc);

  // Field 0 of the closure is the function code pointer, field 1 is
  // the value on which to invoke the method.
  Expression* arg = Expression::make_var_reference(cp, loc);
  arg = Expression::make_dereference(arg, NIL_CHECK_NOT_NEEDED, loc);
  arg = Expression::make_field_reference(arg, 1, loc);

  Expression* bme = Expression::make_bound_method(arg, method, fn, loc);

  const Typed_identifier_list* orig_params = orig_fntype->parameters();
  Expression_list* args;
  if (orig_params == NULL || orig_params->empty())
    args = NULL;
  else
    {
      const Typed_identifier_list* new_params = new_fntype->parameters();
      args = new Expression_list();
      for (Typed_identifier_list::const_iterator p = new_params->begin();
	   p != new_params->end();
	   ++p)
	{
	  Named_object* p_no = gogo->lookup(p->name(), NULL);
	  go_assert(p_no != NULL
		    && p_no->is_variable()
		    && p_no->var_value()->is_parameter());
	  args->push_back(Expression::make_var_reference(p_no, loc));
	}
    }

  Call_expression* call = Expression::make_call(bme, args,
						orig_fntype->is_varargs(),
						loc);
  call->set_varargs_are_lowered();

  Statement* s = Statement::make_return_from_call(call, loc);
  gogo->add_statement(s);
  Block* b = gogo->finish_block(loc);
  gogo->add_block(b, loc);
  gogo->lower_block(new_no, b);
  gogo->flatten_block(new_no, b);
  gogo->finish_function(loc);

  ins.first->second = new_no;
  return new_no;
}

// Return an expression to check *REF for nil while dereferencing
// according to FIELD_INDEXES.  Update *REF to build up the field
// reference.  This is a static function so that we don't have to
// worry about declaring Field_indexes in expressions.h.

static Expression*
bme_check_nil(const Method::Field_indexes* field_indexes, Location loc,
	      Expression** ref)
{
  if (field_indexes == NULL)
    return Expression::make_boolean(false, loc);
  Expression* cond = bme_check_nil(field_indexes->next, loc, ref);
  Struct_type* stype = (*ref)->type()->deref()->struct_type();
  go_assert(stype != NULL
	    && field_indexes->field_index < stype->field_count());
  if ((*ref)->type()->struct_type() == NULL)
    {
      go_assert((*ref)->type()->points_to() != NULL);
      Expression* n = Expression::make_binary(OPERATOR_EQEQ, *ref,
					      Expression::make_nil(loc),
					      loc);
      cond = Expression::make_binary(OPERATOR_OROR, cond, n, loc);
      *ref = Expression::make_dereference(*ref, Expression::NIL_CHECK_DEFAULT,
                                          loc);
      go_assert((*ref)->type()->struct_type() == stype);
    }
  *ref = Expression::make_field_reference(*ref, field_indexes->field_index,
					  loc);
  return cond;
}

// Flatten a method value into a struct with nil checks.  We can't do
// this in the lowering phase, because if the method value is called
// directly we don't need a thunk.  That case will have been handled
// by Call_expression::do_lower, so if we get here then we do need a
// thunk.

Expression*
Bound_method_expression::do_flatten(Gogo* gogo, Named_object*,
				    Statement_inserter* inserter)
{
  Location loc = this->location();

  Named_object* thunk = Bound_method_expression::create_thunk(gogo,
							      this->method_,
							      this->function_);
  if (thunk->is_erroneous())
    {
      go_assert(saw_errors());
      return Expression::make_error(loc);
    }

  // Force the expression into a variable.  This is only necessary if
  // we are going to do nil checks below, but it's easy enough to
  // always do it.
  Expression* expr = this->expr_;
  if (!expr->is_multi_eval_safe())
    {
      Temporary_statement* etemp = Statement::make_temporary(NULL, expr, loc);
      inserter->insert(etemp);
      expr = Expression::make_temporary_reference(etemp, loc);
    }

  // If the method expects a value, and we have a pointer, we need to
  // dereference the pointer.

  Named_object* fn = this->method_->named_object();
  Function_type *fntype;
  if (fn->is_function())
    fntype = fn->func_value()->type();
  else if (fn->is_function_declaration())
    fntype = fn->func_declaration_value()->type();
  else
    go_unreachable();

  Expression* val = expr;
  if (fntype->receiver()->type()->points_to() == NULL
      && val->type()->points_to() != NULL)
    val = Expression::make_dereference(val, NIL_CHECK_DEFAULT, loc);

  // Note that we are ignoring this->expr_type_ here.  The thunk will
  // expect a closure whose second field has type this->expr_type_ (if
  // that is not NULL).  We are going to pass it a closure whose
  // second field has type this->expr_->type().  Since
  // this->expr_type_ is only not-NULL for pointer types, we can get
  // away with this.

  Struct_field_list* fields = new Struct_field_list();
  fields->push_back(Struct_field(Typed_identifier("fn",
						  thunk->func_value()->type(),
						  loc)));
  fields->push_back(Struct_field(Typed_identifier("val", val->type(), loc)));
  Struct_type* st = Type::make_struct_type(fields, loc);
  st->set_is_struct_incomparable();

  Expression_list* vals = new Expression_list();
  vals->push_back(Expression::make_func_code_reference(thunk, loc));
  vals->push_back(val);

  Expression* ret = Expression::make_struct_composite_literal(st, vals, loc);
  ret = Expression::make_heap_expression(ret, loc);

  Node* node = Node::make_node(this);
  if ((node->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
    ret->heap_expression()->set_allocate_on_stack();
  else if (gogo->compiling_runtime()
	   && gogo->package_name() == "runtime"
	   && !saw_errors())
    go_error_at(loc, "%s escapes to heap, not allowed in runtime",
                node->ast_format(gogo).c_str());

  // If necessary, check whether the expression or any embedded
  // pointers are nil.

  Expression* nil_check = NULL;
  if (this->method_->field_indexes() != NULL)
    {
      Expression* ref = expr;
      nil_check = bme_check_nil(this->method_->field_indexes(), loc, &ref);
      expr = ref;
    }

  if (this->method_->is_value_method() && expr->type()->points_to() != NULL)
    {
      Expression* n = Expression::make_binary(OPERATOR_EQEQ, expr,
					      Expression::make_nil(loc),
					      loc);
      if (nil_check == NULL)
	nil_check = n;
      else
	nil_check = Expression::make_binary(OPERATOR_OROR, nil_check, n, loc);
    }

  if (nil_check != NULL)
    {
      Expression* crash = Runtime::make_call(Runtime::PANIC_MEM, loc, 0);
      // Fix the type of the conditional expression by pretending to
      // evaluate to RET either way through the conditional.
      crash = Expression::make_compound(crash, ret, loc);
      ret = Expression::make_conditional(nil_check, crash, ret, loc);
    }

  // RET is a pointer to a struct, but we want a function type.
  ret = Expression::make_unsafe_cast(this->type(), ret, loc);

  return ret;
}

// Dump ast representation of a bound method expression.

void
Bound_method_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  if (this->expr_type_ != NULL)
    ast_dump_context->ostream() << "(";
  ast_dump_context->dump_expression(this->expr_);
  if (this->expr_type_ != NULL)
    {
      ast_dump_context->ostream() << ":";
      ast_dump_context->dump_type(this->expr_type_);
      ast_dump_context->ostream() << ")";
    }

  ast_dump_context->ostream() << "." << this->function_->name();
}

// Make a method expression.

Bound_method_expression*
Expression::make_bound_method(Expression* expr, const Method* method,
			      Named_object* function, Location location)
{
  return new Bound_method_expression(expr, method, function, location);
}

// Class Builtin_call_expression.  This is used for a call to a
// builtin function.

Builtin_call_expression::Builtin_call_expression(Gogo* gogo,
						 Expression* fn,
						 Expression_list* args,
						 bool is_varargs,
						 Location location)
  : Call_expression(fn, args, is_varargs, location),
    gogo_(gogo), code_(BUILTIN_INVALID), seen_(false),
    recover_arg_is_set_(false)
{
  Func_expression* fnexp = this->fn()->func_expression();
  if (fnexp == NULL)
    {
      this->code_ = BUILTIN_INVALID;
      return;
    }
  const std::string& name(fnexp->named_object()->name());
  if (name == "append")
    this->code_ = BUILTIN_APPEND;
  else if (name == "cap")
    this->code_ = BUILTIN_CAP;
  else if (name == "close")
    this->code_ = BUILTIN_CLOSE;
  else if (name == "complex")
    this->code_ = BUILTIN_COMPLEX;
  else if (name == "copy")
    this->code_ = BUILTIN_COPY;
  else if (name == "delete")
    this->code_ = BUILTIN_DELETE;
  else if (name == "imag")
    this->code_ = BUILTIN_IMAG;
  else if (name == "len")
    this->code_ = BUILTIN_LEN;
  else if (name == "make")
    this->code_ = BUILTIN_MAKE;
  else if (name == "new")
    this->code_ = BUILTIN_NEW;
  else if (name == "panic")
    this->code_ = BUILTIN_PANIC;
  else if (name == "print")
    this->code_ = BUILTIN_PRINT;
  else if (name == "println")
    this->code_ = BUILTIN_PRINTLN;
  else if (name == "real")
    this->code_ = BUILTIN_REAL;
  else if (name == "recover")
    this->code_ = BUILTIN_RECOVER;
  else if (name == "Alignof")
    this->code_ = BUILTIN_ALIGNOF;
  else if (name == "Offsetof")
    this->code_ = BUILTIN_OFFSETOF;
  else if (name == "Sizeof")
    this->code_ = BUILTIN_SIZEOF;
  else
    go_unreachable();
}

// Return whether this is a call to recover.  This is a virtual
// function called from the parent class.

bool
Builtin_call_expression::do_is_recover_call() const
{
  if (this->classification() == EXPRESSION_ERROR)
    return false;
  return this->code_ == BUILTIN_RECOVER;
}

// Set the argument for a call to recover.

void
Builtin_call_expression::do_set_recover_arg(Expression* arg)
{
  const Expression_list* args = this->args();
  go_assert(args == NULL || args->empty());
  Expression_list* new_args = new Expression_list();
  new_args->push_back(arg);
  this->set_args(new_args);
  this->recover_arg_is_set_ = true;
}

// Lower a builtin call expression.  This turns new and make into
// specific expressions.  We also convert to a constant if we can.

Expression*
Builtin_call_expression::do_lower(Gogo*, Named_object* function,
				  Statement_inserter* inserter, int)
{
  if (this->is_error_expression())
    return this;

  Location loc = this->location();

  if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
    {
      this->report_error(_("invalid use of %<...%> with builtin function"));
      return Expression::make_error(loc);
    }

  if (this->code_ == BUILTIN_OFFSETOF)
    {
      Expression* arg = this->one_arg();

      if (arg->bound_method_expression() != NULL
	  || arg->interface_field_reference_expression() != NULL)
	{
	  this->report_error(_("invalid use of method value as argument "
			       "of Offsetof"));
	  return this;
	}

      Field_reference_expression* farg = arg->field_reference_expression();
      while (farg != NULL)
	{
	  if (!farg->implicit())
	    break;
	  // When the selector refers to an embedded field,
	  // it must not be reached through pointer indirections.
	  if (farg->expr()->deref() != farg->expr())
	    {
	      this->report_error(_("argument of Offsetof implies "
				   "indirection of an embedded field"));
	      return this;
	    }
	  // Go up until we reach the original base.
	  farg = farg->expr()->field_reference_expression();
	}
    }

  if (this->is_constant())
    {
      Numeric_constant nc;
      if (this->numeric_constant_value(&nc))
	return nc.expression(loc);
    }

  switch (this->code_)
    {
    default:
      break;

    case BUILTIN_NEW:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->size() < 1)
	  this->report_error(_("not enough arguments"));
	else if (args->size() > 1)
	  this->report_error(_("too many arguments"));
	else
	  {
	    Expression* arg = args->front();
	    if (!arg->is_type_expression())
	      {
		go_error_at(arg->location(), "expected type");
		this->set_is_error();
	      }
	    else
	      return Expression::make_allocation(arg->type(), loc);
	  }
      }
      break;

    case BUILTIN_MAKE:
      return this->lower_make(inserter);

    case BUILTIN_RECOVER:
      if (function != NULL)
	function->func_value()->set_calls_recover();
      else
	{
	  // Calling recover outside of a function always returns the
	  // nil empty interface.
	  Type* eface = Type::make_empty_interface_type(loc);
	  return Expression::make_cast(eface, Expression::make_nil(loc), loc);
	}
      break;

    case BUILTIN_DELETE:
      {
        const Expression_list* args = this->args();
        if (args == NULL || args->size() < 2)
          this->report_error(_("not enough arguments"));
        else if (args->size() > 2)
          this->report_error(_("too many arguments"));
        else if (args->front()->type()->map_type() == NULL)
          this->report_error(_("argument 1 must be a map"));
        else
          {
            Type* key_type =
              args->front()->type()->map_type()->key_type();
            Expression_list::iterator pa = this->args()->begin();
            pa++;
            Type* arg_type = (*pa)->type();
            std::string reason;
            if (!Type::are_assignable(key_type, arg_type, &reason))
              {
                if (reason.empty())
                  go_error_at(loc, "argument 2 has incompatible type");
                else
                  go_error_at(loc, "argument 2 has incompatible type (%s)",
                              reason.c_str());
                this->set_is_error();
              }
            else if (!Type::are_identical(key_type, arg_type, 0, NULL))
              *pa = Expression::make_cast(key_type, *pa, loc);
          }
      }
      break;

    case BUILTIN_PRINT:
    case BUILTIN_PRINTLN:
      // Force all the arguments into temporary variables, so that we
      // don't try to evaluate something while holding the print lock.
      if (this->args() == NULL)
	break;
      for (Expression_list::iterator pa = this->args()->begin();
	   pa != this->args()->end();
	   ++pa)
	{
	  if (!(*pa)->is_multi_eval_safe())
	    {
	      Temporary_statement* temp =
		Statement::make_temporary(NULL, *pa, loc);
	      inserter->insert(temp);
	      *pa = Expression::make_temporary_reference(temp, loc);
	    }
	}
      break;
    }

  return this;
}

// Flatten a builtin call expression.  This turns the arguments of some
// builtin calls into temporary expressions.  Also expand copy and append
// to runtime calls.

Expression*
Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
                                    Statement_inserter* inserter)
{
  if (this->is_error_expression())
    {
      go_assert(saw_errors());
      return this;
    }

  Location loc = this->location();

  switch (this->code_)
    {
    default:
      break;

    case BUILTIN_APPEND:
      return this->flatten_append(gogo, function, inserter, NULL, NULL);

    case BUILTIN_COPY:
      {
	Type* at = this->args()->front()->type();
	for (Expression_list::iterator pa = this->args()->begin();
	     pa != this->args()->end();
	     ++pa)
	  {
	    if ((*pa)->is_nil_expression())
	      {
		Expression* nil = Expression::make_nil(loc);
		Expression* zero = Expression::make_integer_ul(0, NULL, loc);
		*pa = Expression::make_slice_value(at, nil, zero, zero, loc);
	      }
	    if (!(*pa)->is_multi_eval_safe())
	      {
		Temporary_statement* temp =
                  Statement::make_temporary(NULL, *pa, loc);
		inserter->insert(temp);
		*pa = Expression::make_temporary_reference(temp, loc);
	      }
	  }

        // Lower to runtime call.
        const Expression_list* args = this->args();
        go_assert(args != NULL && args->size() == 2);
        Expression* arg1 = args->front();
        Expression* arg2 = args->back();
	go_assert(arg1->is_multi_eval_safe());
	go_assert(arg2->is_multi_eval_safe());
        bool arg2_is_string = arg2->type()->is_string_type();

        Expression* ret;
        Type* et = at->array_type()->element_type();
        if (et->has_pointer())
          {
            Expression* td = Expression::make_type_descriptor(et, loc);
	    Expression* pd =
	      Expression::make_slice_info(arg1, SLICE_INFO_VALUE_POINTER, loc);
	    Expression* ld =
	      Expression::make_slice_info(arg1, SLICE_INFO_LENGTH, loc);
	    Expression* ps =
	      Expression::make_slice_info(arg2, SLICE_INFO_VALUE_POINTER, loc);
	    Expression* ls =
	      Expression::make_slice_info(arg2, SLICE_INFO_LENGTH, loc);
            ret = Runtime::make_call(Runtime::TYPEDSLICECOPY, loc,
                                     5, td, pd, ld, ps, ls);
          }
        else
          {
            Type* int_type = Type::lookup_integer_type("int");
            Type* uintptr_type = Type::lookup_integer_type("uintptr");

            // l1 = len(arg1)
            Named_object* lenfn = gogo->lookup_global("len");
            Expression* lenref = Expression::make_func_reference(lenfn, NULL, loc);
            Expression_list* len_args = new Expression_list();
            len_args->push_back(arg1->copy());
            Expression* len1 = Expression::make_call(lenref, len_args, false, loc);
            gogo->lower_expression(function, inserter, &len1);
            gogo->flatten_expression(function, inserter, &len1);
            Temporary_statement* l1tmp = Statement::make_temporary(int_type, len1, loc);
            inserter->insert(l1tmp);

            // l2 = len(arg2)
            len_args = new Expression_list();
            len_args->push_back(arg2->copy());
            Expression* len2 = Expression::make_call(lenref, len_args, false, loc);
            gogo->lower_expression(function, inserter, &len2);
            gogo->flatten_expression(function, inserter, &len2);
            Temporary_statement* l2tmp = Statement::make_temporary(int_type, len2, loc);
            inserter->insert(l2tmp);

            // n = (l1 < l2 ? l1 : l2)
            Expression* l1ref = Expression::make_temporary_reference(l1tmp, loc);
            Expression* l2ref = Expression::make_temporary_reference(l2tmp, loc);
            Expression* cond = Expression::make_binary(OPERATOR_LT, l1ref, l2ref, loc);
            Expression* n = Expression::make_conditional(cond,
                                                         l1ref->copy(),
                                                         l2ref->copy(),
                                                         loc);
            Temporary_statement* ntmp = Statement::make_temporary(NULL, n, loc);
            inserter->insert(ntmp);

            // sz = n * sizeof(elem_type)
            Expression* nref = Expression::make_temporary_reference(ntmp, loc);
            nref = Expression::make_cast(uintptr_type, nref, loc);
            Expression* sz = Expression::make_type_info(et, TYPE_INFO_SIZE);
            sz = Expression::make_binary(OPERATOR_MULT, sz, nref, loc);

            // memmove(arg1.ptr, arg2.ptr, sz)
            Expression* p1 = Expression::make_slice_info(arg1,
                                                         SLICE_INFO_VALUE_POINTER,
                                                         loc);
            Expression* p2 = (arg2_is_string
                              ? Expression::make_string_info(arg2,
                                                             STRING_INFO_DATA,
                                                             loc)
                              : Expression::make_slice_info(arg2,
                                                            SLICE_INFO_VALUE_POINTER,
                                                            loc));
            Expression* call = Runtime::make_call(Runtime::BUILTIN_MEMMOVE, loc, 3,
                                                  p1, p2, sz);

            // n is the return value of copy
            nref = Expression::make_temporary_reference(ntmp, loc);
            ret = Expression::make_compound(call, nref, loc);
          }
        return ret;
      }
      break;

    case BUILTIN_PANIC:
      for (Expression_list::iterator pa = this->args()->begin();
	   pa != this->args()->end();
	   ++pa)
	{
	  if (!(*pa)->is_multi_eval_safe()
	      && (*pa)->type()->interface_type() != NULL)
	    {
	      Temporary_statement* temp =
		Statement::make_temporary(NULL, *pa, loc);
	      inserter->insert(temp);
	      *pa = Expression::make_temporary_reference(temp, loc);
	    }
	}
      break;

    case BUILTIN_LEN:
    case BUILTIN_CAP:
      {
	Expression_list::iterator pa = this->args()->begin();
	if (!(*pa)->is_multi_eval_safe()
	    && ((*pa)->type()->map_type() != NULL
		|| (*pa)->type()->channel_type() != NULL))
	  {
	    Temporary_statement* temp =
	      Statement::make_temporary(NULL, *pa, loc);
	    inserter->insert(temp);
	    *pa = Expression::make_temporary_reference(temp, loc);
	  }
      }
      break;

    case BUILTIN_DELETE:
      {
        // Lower to a runtime function call.
        const Expression_list* args = this->args();

        // Since this function returns no value it must appear in
        // a statement by itself, so we don't have to worry about
        // order of evaluation of values around it.  Evaluate the
        // map first to get order of evaluation right.
        Map_type* mt = args->front()->type()->map_type();
        Temporary_statement* map_temp =
          Statement::make_temporary(mt, args->front(), loc);
        inserter->insert(map_temp);

        Temporary_statement* key_temp =
          Statement::make_temporary(mt->key_type(), args->back(), loc);
        inserter->insert(key_temp);

        Expression* e1 = Expression::make_type_descriptor(mt, loc);
        Expression* e2 = Expression::make_temporary_reference(map_temp,
                                                              loc);
        Expression* e3 = Expression::make_temporary_reference(key_temp,
                                                              loc);

        Runtime::Function code;
        switch (mt->algorithm(gogo))
          {
            case Map_type::MAP_ALG_FAST32:
            case Map_type::MAP_ALG_FAST32PTR:
              {
                code = Runtime::MAPDELETE_FAST32;
                Type* uint32_type = Type::lookup_integer_type("uint32");
                Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
                e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
                e3 = Expression::make_unsafe_cast(uint32_ptr_type, e3,
                                                  loc);
                e3 = Expression::make_dereference(e3,
                                                  Expression::NIL_CHECK_NOT_NEEDED,
                                                  loc);
                break;
              }
            case Map_type::MAP_ALG_FAST64:
            case Map_type::MAP_ALG_FAST64PTR:
              {
                code = Runtime::MAPDELETE_FAST64;
                Type* uint64_type = Type::lookup_integer_type("uint64");
                Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
                e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
                e3 = Expression::make_unsafe_cast(uint64_ptr_type, e3,
                                                  loc);
                e3 = Expression::make_dereference(e3,
                                                  Expression::NIL_CHECK_NOT_NEEDED,
                                                  loc);
                break;
              }
            case Map_type::MAP_ALG_FASTSTR:
              code = Runtime::MAPDELETE_FASTSTR;
              break;
            default:
              code = Runtime::MAPDELETE;

              // If the call to delete is deferred, and is in a loop,
              // then the loop will only have a single instance of the
              // temporary variable.  Passing the address of the
              // temporary variable here means that the deferred call
              // will see the last value in the loop, not the current
              // value.  So for this unusual case copy the value into
              // the heap.
              if (!this->is_deferred())
                e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
              else
                {
                  Expression* a = Expression::make_allocation(mt->key_type(),
                                                              loc);
                  Temporary_statement* atemp =
                    Statement::make_temporary(NULL, a, loc);
                  inserter->insert(atemp);

                  a = Expression::make_temporary_reference(atemp, loc);
                  a = Expression::make_dereference(a, NIL_CHECK_NOT_NEEDED, loc);
                  Statement* s = Statement::make_assignment(a, e3, loc);
                  inserter->insert(s);

                  e3 = Expression::make_temporary_reference(atemp, loc);
                }
          }

        return Runtime::make_call(code, loc, 3, e1, e2, e3);
      }
    }

  return this;
}

// Lower a make expression.

Expression*
Builtin_call_expression::lower_make(Statement_inserter* inserter)
{
  Location loc = this->location();

  const Expression_list* args = this->args();
  if (args == NULL || args->size() < 1)
    {
      this->report_error(_("not enough arguments"));
      return Expression::make_error(this->location());
    }

  Expression_list::const_iterator parg = args->begin();

  Expression* first_arg = *parg;
  if (!first_arg->is_type_expression())
    {
      go_error_at(first_arg->location(), "expected type");
      this->set_is_error();
      return Expression::make_error(this->location());
    }
  Type* type = first_arg->type();

  if (!type->in_heap())
    go_error_at(first_arg->location(),
		"cannot make slice of go:notinheap type");

  bool is_slice = false;
  bool is_map = false;
  bool is_chan = false;
  if (type->is_slice_type())
    is_slice = true;
  else if (type->map_type() != NULL)
    is_map = true;
  else if (type->channel_type() != NULL)
    is_chan = true;
  else
    {
      this->report_error(_("invalid type for make function"));
      return Expression::make_error(this->location());
    }

  Type_context int_context(Type::lookup_integer_type("int"), false);

  ++parg;
  Expression* len_arg;
  bool len_small = false;
  if (parg == args->end())
    {
      if (is_slice)
	{
	  this->report_error(_("length required when allocating a slice"));
	  return Expression::make_error(this->location());
	}
      len_arg = Expression::make_integer_ul(0, NULL, loc);
      len_small = true;
    }
  else
    {
      len_arg = *parg;
      len_arg->determine_type(&int_context);
      if (len_arg->type()->integer_type() == NULL)
	{
	  go_error_at(len_arg->location(), "non-integer len argument in make");
	  return Expression::make_error(this->location());
	}
      if (!this->check_int_value(len_arg, true, &len_small))
	return Expression::make_error(this->location());
      ++parg;
    }

  Expression* cap_arg = NULL;
  bool cap_small = false;
  Numeric_constant nclen;
  Numeric_constant nccap;
  unsigned long vlen;
  unsigned long vcap;
  if (is_slice && parg != args->end())
    {
      cap_arg = *parg;
      cap_arg->determine_type(&int_context);
      if (cap_arg->type()->integer_type() == NULL)
	{
	  go_error_at(cap_arg->location(), "non-integer cap argument in make");
	  return Expression::make_error(this->location());
	}
      if (!this->check_int_value(cap_arg, false, &cap_small))
	return Expression::make_error(this->location());

      if (len_arg->numeric_constant_value(&nclen)
	  && cap_arg->numeric_constant_value(&nccap)
	  && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
	  && nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID
	  && vlen > vcap)
	{
	  this->report_error(_("len larger than cap"));
	  return Expression::make_error(this->location());
	}

      ++parg;
    }

  if (parg != args->end())
    {
      this->report_error(_("too many arguments to make"));
      return Expression::make_error(this->location());
    }

  Location type_loc = first_arg->location();

  Expression* call;
  if (is_slice)
    {
      Temporary_statement* len_temp = NULL;
      if (!len_arg->is_constant())
	{
	  len_temp = Statement::make_temporary(NULL, len_arg, loc);
	  inserter->insert(len_temp);
	  len_arg = Expression::make_temporary_reference(len_temp, loc);
	}

      if (cap_arg == NULL)
	{
          cap_small = len_small;
	  if (len_temp == NULL)
	    cap_arg = len_arg->copy();
	  else
	    cap_arg = Expression::make_temporary_reference(len_temp, loc);
	}
      else if (!cap_arg->is_constant())
	{
	  Temporary_statement* cap_temp = Statement::make_temporary(NULL,
								    cap_arg,
								    loc);
	  inserter->insert(cap_temp);
	  cap_arg = Expression::make_temporary_reference(cap_temp, loc);
	}

      Type* et = type->array_type()->element_type();
      Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
      Runtime::Function code = Runtime::MAKESLICE;
      if (!len_small || !cap_small)
	code = Runtime::MAKESLICE64;
      Expression* mem = Runtime::make_call(code, loc, 3, type_arg, len_arg,
					   cap_arg);
      mem = Expression::make_unsafe_cast(Type::make_pointer_type(et), mem,
					 loc);
      Type* int_type = Type::lookup_integer_type("int");
      len_arg = Expression::make_cast(int_type, len_arg->copy(), loc);
      cap_arg = Expression::make_cast(int_type, cap_arg->copy(), loc);
      call = Expression::make_slice_value(type, mem, len_arg, cap_arg, loc);
    }
  else if (is_map)
    {
      Expression* type_arg = Expression::make_type_descriptor(type, type_loc);
      if (!len_small)
	call = Runtime::make_call(Runtime::MAKEMAP64, loc, 3, type_arg,
				  len_arg,
				  Expression::make_nil(loc));
      else
	{
	  if (len_arg->numeric_constant_value(&nclen)
	      && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
	      && vlen <= Map_type::bucket_size)
	    call = Runtime::make_call(Runtime::MAKEMAP_SMALL, loc, 0);
	  else
	    call = Runtime::make_call(Runtime::MAKEMAP, loc, 3, type_arg,
				      len_arg,
				      Expression::make_nil(loc));
	}
    }
  else if (is_chan)
    {
      Expression* type_arg = Expression::make_type_descriptor(type, type_loc);
      Runtime::Function code = Runtime::MAKECHAN;
      if (!len_small)
	code = Runtime::MAKECHAN64;
      call = Runtime::make_call(code, loc, 2, type_arg, len_arg);
    }
  else
    go_unreachable();

  return Expression::make_unsafe_cast(type, call, loc);
}

// Flatten a call to the predeclared append function.  We do this in
// the flatten phase, not the lowering phase, so that we run after
// type checking and after order_evaluations.  If ASSIGN_LHS is not
// NULL, this append is the right-hand-side of an assignment and
// ASSIGN_LHS is the left-hand-side; in that case, set LHS directly
// rather than returning a slice.  This lets us omit a write barrier
// in common cases like a = append(a, ...) when the slice does not
// need to grow.  ENCLOSING is not NULL iff ASSIGN_LHS is not NULL.

Expression*
Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
					Statement_inserter* inserter,
					Expression* assign_lhs,
					Block* enclosing)
{
  if (this->is_error_expression())
    return this;

  Location loc = this->location();

  const Expression_list* args = this->args();
  go_assert(args != NULL && !args->empty());

  Type* slice_type = args->front()->type();
  go_assert(slice_type->is_slice_type());
  Type* element_type = slice_type->array_type()->element_type();

  if (args->size() == 1)
    {
      // append(s) evaluates to s.
      if (assign_lhs != NULL)
	return NULL;
      return args->front();
    }

  Type* int_type = Type::lookup_integer_type("int");
  Type* uint_type = Type::lookup_integer_type("uint");

  // Implementing
  //   append(s1, s2...)
  // or
  //   append(s1, a1, a2, a3, ...)

  // s1tmp := s1
  Temporary_statement* s1tmp = Statement::make_temporary(NULL, args->front(),
							 loc);
  inserter->insert(s1tmp);

  // l1tmp := len(s1tmp)
  Named_object* lenfn = gogo->lookup_global("len");
  Expression* lenref = Expression::make_func_reference(lenfn, NULL, loc);
  Expression_list* call_args = new Expression_list();
  call_args->push_back(Expression::make_temporary_reference(s1tmp, loc));
  Expression* len = Expression::make_call(lenref, call_args, false, loc);
  gogo->lower_expression(function, inserter, &len);
  gogo->flatten_expression(function, inserter, &len);
  Temporary_statement* l1tmp = Statement::make_temporary(int_type, len, loc);
  inserter->insert(l1tmp);

  Temporary_statement* s2tmp = NULL;
  Temporary_statement* l2tmp = NULL;
  Expression_list* add = NULL;
  Expression* len2;
  Call_expression* makecall = NULL;
  if (this->is_varargs())
    {
      go_assert(args->size() == 2);

      std::pair<Call_expression*, Temporary_statement*> p =
        Expression::find_makeslice_call(args->back());
      makecall = p.first;
      if (makecall != NULL)
        {
          // We are handling
          // 	append(s, make([]T, len[, cap])...))
          // which has already been lowered to
          // 	append(s, runtime.makeslice(T, len, cap)).
          // We will optimize this to directly zeroing the tail,
          // instead of allocating a new slice then copy.

          // Retrieve the length and capacity. Cannot reference s2 as
          // we will remove the makeslice call.
          Expression* len_arg = makecall->args()->at(1);
          len_arg = Expression::make_cast(int_type, len_arg, loc);
          l2tmp = Statement::make_temporary(int_type, len_arg, loc);
          inserter->insert(l2tmp);

          Expression* cap_arg = makecall->args()->at(2);
          cap_arg = Expression::make_cast(int_type, cap_arg, loc);
          Temporary_statement* c2tmp =
            Statement::make_temporary(int_type, cap_arg, loc);
          inserter->insert(c2tmp);

          // Check bad len/cap here.
	  // checkmakeslice(type, len, cap)
	  // (Note that if len and cap are constants, we won't see a
	  // makeslice call here, as it will be rewritten to a stack
	  // allocated array by Mark_address_taken::expression.)
	  Expression* elem = Expression::make_type_descriptor(element_type,
							      loc);
          len2 = Expression::make_temporary_reference(l2tmp, loc);
          Expression* cap2 = Expression::make_temporary_reference(c2tmp, loc);
	  Expression* check = Runtime::make_call(Runtime::CHECK_MAKE_SLICE,
						 loc, 3, elem, len2, cap2);
          gogo->lower_expression(function, inserter, &check);
          gogo->flatten_expression(function, inserter, &check);
          Statement* s = Statement::make_statement(check, false);
          inserter->insert(s);

          // Remove the original makeslice call.
          Temporary_statement* ts = p.second;
          if (ts != NULL && ts->uses() == 1)
            ts->set_init(Expression::make_nil(loc));
        }
      else
        {
          // s2tmp := s2
          s2tmp = Statement::make_temporary(NULL, args->back(), loc);
          inserter->insert(s2tmp);

          // l2tmp := len(s2tmp)
          lenref = Expression::make_func_reference(lenfn, NULL, loc);
          call_args = new Expression_list();
          call_args->push_back(Expression::make_temporary_reference(s2tmp, loc));
          len = Expression::make_call(lenref, call_args, false, loc);
          gogo->lower_expression(function, inserter, &len);
          gogo->flatten_expression(function, inserter, &len);
          l2tmp = Statement::make_temporary(int_type, len, loc);
          inserter->insert(l2tmp);
        }

      // len2 = l2tmp
      len2 = Expression::make_temporary_reference(l2tmp, loc);
    }
  else
    {
      // We have to ensure that all the arguments are in variables
      // now, because otherwise if one of them is an index expression
      // into the current slice we could overwrite it before we fetch
      // it.
      add = new Expression_list();
      Expression_list::const_iterator pa = args->begin();
      for (++pa; pa != args->end(); ++pa)
	{
	  if ((*pa)->is_multi_eval_safe())
	    add->push_back(*pa);
	  else
	    {
	      Temporary_statement* tmp = Statement::make_temporary(NULL, *pa,
								   loc);
	      inserter->insert(tmp);
	      add->push_back(Expression::make_temporary_reference(tmp, loc));
	    }
	}

      // len2 = len(add)
      len2 = Expression::make_integer_ul(add->size(), int_type, loc);
    }

  // ntmp := l1tmp + len2
  Expression* ref = Expression::make_temporary_reference(l1tmp, loc);
  Expression* sum = Expression::make_binary(OPERATOR_PLUS, ref, len2, loc);
  gogo->lower_expression(function, inserter, &sum);
  gogo->flatten_expression(function, inserter, &sum);
  Temporary_statement* ntmp = Statement::make_temporary(int_type, sum, loc);
  inserter->insert(ntmp);

  // s1tmp = uint(ntmp) > uint(cap(s1tmp)) ?
  //   growslice(type, s1tmp, ntmp) :
  //   s1tmp[:ntmp]
  // Using uint here means that if the computation of ntmp overflowed,
  // we will call growslice which will panic.

  Named_object* capfn = gogo->lookup_global("cap");
  Expression* capref = Expression::make_func_reference(capfn, NULL, loc);
  call_args = new Expression_list();
  call_args->push_back(Expression::make_temporary_reference(s1tmp, loc));
  Expression* cap = Expression::make_call(capref, call_args, false, loc);
  gogo->lower_expression(function, inserter, &cap);
  gogo->flatten_expression(function, inserter, &cap);
  Temporary_statement* c1tmp = Statement::make_temporary(int_type, cap, loc);
  inserter->insert(c1tmp);

  Expression* left = Expression::make_temporary_reference(ntmp, loc);
  left = Expression::make_cast(uint_type, left, loc);
  Expression* right = Expression::make_temporary_reference(c1tmp, loc);
  right = Expression::make_cast(uint_type, right, loc);

  Expression* cond = Expression::make_binary(OPERATOR_GT, left, right, loc);

  Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
  Expression* a1 = Expression::make_type_descriptor(element_type, loc);
  Expression* a2 = Expression::make_temporary_reference(s1tmp, loc);
  a2 = slice_type->array_type()->get_value_pointer(gogo, a2, false);
  a2 = Expression::make_cast(unsafe_ptr_type, a2, loc);
  Expression* a3 = Expression::make_temporary_reference(l1tmp, loc);
  Expression* a4 = Expression::make_temporary_reference(c1tmp, loc);
  Expression* a5 = Expression::make_temporary_reference(ntmp, loc);
  Expression* call = Runtime::make_call(Runtime::GROWSLICE, loc, 5,
					a1, a2, a3, a4, a5);
  call = Expression::make_unsafe_cast(slice_type, call, loc);

  ref = Expression::make_temporary_reference(s1tmp, loc);
  Expression* zero = Expression::make_integer_ul(0, int_type, loc);
  Expression* ref2 = Expression::make_temporary_reference(ntmp, loc);
  ref = Expression::make_array_index(ref, zero, ref2, NULL, loc);
  ref->array_index_expression()->set_needs_bounds_check(false);

  if (assign_lhs == NULL)
    {
      Expression* rhs = Expression::make_conditional(cond, call, ref, loc);

      gogo->lower_expression(function, inserter, &rhs);
      gogo->flatten_expression(function, inserter, &rhs);

      ref = Expression::make_temporary_reference(s1tmp, loc);
      Statement* assign = Statement::make_assignment(ref, rhs, loc);
      inserter->insert(assign);
    }
  else
    {
      gogo->lower_expression(function, inserter, &cond);
      gogo->flatten_expression(function, inserter, &cond);
      gogo->lower_expression(function, inserter, &call);
      gogo->flatten_expression(function, inserter, &call);
      gogo->lower_expression(function, inserter, &ref);
      gogo->flatten_expression(function, inserter, &ref);

      Block* then_block = new Block(enclosing, loc);
      Assignment_statement* assign =
	Statement::make_assignment(assign_lhs, call, loc);
      then_block->add_statement(assign);

      Block* else_block = new Block(enclosing, loc);
      assign = Statement::make_assignment(assign_lhs->copy(), ref, loc);
      // This assignment will not change the pointer value, so it does
      // not need a write barrier.
      assign->set_omit_write_barrier();
      else_block->add_statement(assign);

      Statement* s = Statement::make_if_statement(cond, then_block,
						  else_block, loc);
      inserter->insert(s);

      ref = Expression::make_temporary_reference(s1tmp, loc);
      assign = Statement::make_assignment(ref, assign_lhs->copy(), loc);
      inserter->insert(assign);
    }

  Type* uintptr_type = Type::lookup_integer_type("uintptr");

  if (this->is_varargs())
    {
      if (makecall != NULL)
        {
          // memclr(&s1tmp[l1tmp], l2tmp*sizeof(elem))
          a1 = Expression::make_temporary_reference(s1tmp, loc);
          ref = Expression::make_temporary_reference(l1tmp, loc);
          a1 = Expression::make_array_index(a1, ref, NULL, NULL, loc);
          a1->array_index_expression()->set_needs_bounds_check(false);
          a1 = Expression::make_unary(OPERATOR_AND, a1, loc);

          ref = Expression::make_temporary_reference(l2tmp, loc);
          ref = Expression::make_cast(uintptr_type, ref, loc);
          a2 = Expression::make_type_info(element_type, TYPE_INFO_SIZE);
          a2 = Expression::make_binary(OPERATOR_MULT, a2, ref, loc);

          if (element_type->has_pointer())
            call = Runtime::make_call(Runtime::MEMCLRHASPTR, loc, 2, a1, a2);
          else
            {
              Type* int32_type = Type::lookup_integer_type("int32");
              zero = Expression::make_integer_ul(0, int32_type, loc);
              call = Runtime::make_call(Runtime::BUILTIN_MEMSET, loc, 3, a1,
                                        zero, a2);
            }

          if (element_type->has_pointer())
            {
              // For a slice containing pointers, growslice already zeroed
              // the memory. We only need to zero in non-growing case.
              // Note: growslice does not zero the memory in non-pointer case.
              ref = Expression::make_temporary_reference(ntmp, loc);
              ref = Expression::make_cast(uint_type, ref, loc);
              ref2 = Expression::make_temporary_reference(c1tmp, loc);
              ref2 = Expression::make_cast(uint_type, ref2, loc);
              cond = Expression::make_binary(OPERATOR_GT, ref, ref2, loc);
              zero = Expression::make_integer_ul(0, int_type, loc);
              call = Expression::make_conditional(cond, call, zero, loc);
            }
        }
      else
        {
          if (element_type->has_pointer())
            {
              // copy(s1tmp[l1tmp:], s2tmp)
              a1 = Expression::make_temporary_reference(s1tmp, loc);
              ref = Expression::make_temporary_reference(l1tmp, loc);
              Expression* nil = Expression::make_nil(loc);
              a1 = Expression::make_array_index(a1, ref, nil, NULL, loc);
              a1->array_index_expression()->set_needs_bounds_check(false);

              a2 = Expression::make_temporary_reference(s2tmp, loc);

              Named_object* copyfn = gogo->lookup_global("copy");
              Expression* copyref = Expression::make_func_reference(copyfn, NULL, loc);
              call_args = new Expression_list();
              call_args->push_back(a1);
              call_args->push_back(a2);
              call = Expression::make_call(copyref, call_args, false, loc);
            }
          else
            {
              // memmove(&s1tmp[l1tmp], s2tmp.ptr, l2tmp*sizeof(elem))
              a1 = Expression::make_temporary_reference(s1tmp, loc);
              ref = Expression::make_temporary_reference(l1tmp, loc);
              a1 = Expression::make_array_index(a1, ref, NULL, NULL, loc);
              a1->array_index_expression()->set_needs_bounds_check(false);
              a1 = Expression::make_unary(OPERATOR_AND, a1, loc);

              a2 = Expression::make_temporary_reference(s2tmp, loc);
              a2 = (a2->type()->is_string_type()
                    ? Expression::make_string_info(a2,
                                                   STRING_INFO_DATA,
                                                   loc)
                    : Expression::make_slice_info(a2,
                                                  SLICE_INFO_VALUE_POINTER,
                                                  loc));

              ref = Expression::make_temporary_reference(l2tmp, loc);
              ref = Expression::make_cast(uintptr_type, ref, loc);
              a3 = Expression::make_type_info(element_type, TYPE_INFO_SIZE);
              a3 = Expression::make_binary(OPERATOR_MULT, a3, ref, loc);

              call = Runtime::make_call(Runtime::BUILTIN_MEMMOVE, loc, 3,
                                        a1, a2, a3);
            }
        }
      gogo->lower_expression(function, inserter, &call);
      gogo->flatten_expression(function, inserter, &call);
      inserter->insert(Statement::make_statement(call, false));
    }
  else
    {
      // For each argument:
      //  s1tmp[l1tmp+i] = a
      unsigned long i = 0;
      for (Expression_list::const_iterator pa = add->begin();
	   pa != add->end();
	   ++pa, ++i)
	{
	  ref = Expression::make_temporary_reference(s1tmp, loc);
	  ref2 = Expression::make_temporary_reference(l1tmp, loc);
	  Expression* off = Expression::make_integer_ul(i, int_type, loc);
	  ref2 = Expression::make_binary(OPERATOR_PLUS, ref2, off, loc);
	  Expression* lhs = Expression::make_array_index(ref, ref2, NULL,
                                                         NULL, loc);
          lhs->array_index_expression()->set_needs_bounds_check(false);
	  gogo->lower_expression(function, inserter, &lhs);
	  gogo->flatten_expression(function, inserter, &lhs);
      Expression* elem = *pa;
      if (!Type::are_identical(element_type, elem->type(), 0, NULL)
          && element_type->interface_type() != NULL)
        elem = Expression::make_cast(element_type, elem, loc);
	  // The flatten pass runs after the write barrier pass, so we
	  // need to insert a write barrier here if necessary.
	  // However, if ASSIGN_LHS is not NULL, we have been called
	  // directly before the write barrier pass.
	  Statement* assign;
	  if (assign_lhs != NULL
	      || !gogo->assign_needs_write_barrier(lhs, NULL))
	    assign = Statement::make_assignment(lhs, elem, loc);
	  else
	    {
	      Function* f = function == NULL ? NULL : function->func_value();
	      assign = gogo->assign_with_write_barrier(f, NULL, inserter,
						       lhs, elem, loc);
	    }
	  inserter->insert(assign);
	}
    }

  if (assign_lhs != NULL)
    return NULL;

  return Expression::make_temporary_reference(s1tmp, loc);
}

// Return whether an expression has an integer value.  Report an error
// if not.  This is used when handling calls to the predeclared make
// function.  Set *SMALL if the value is known to fit in type "int".

bool
Builtin_call_expression::check_int_value(Expression* e, bool is_length,
					 bool *small)
{
  *small = false;

  Numeric_constant nc;
  if (e->numeric_constant_value(&nc))
    {
      unsigned long v;
      switch (nc.to_unsigned_long(&v))
	{
	case Numeric_constant::NC_UL_VALID:
	  break;
	case Numeric_constant::NC_UL_NOTINT:
	  go_error_at(e->location(), "non-integer %s argument to make",
		      is_length ? "len" : "cap");
	  return false;
	case Numeric_constant::NC_UL_NEGATIVE:
	  go_error_at(e->location(), "negative %s argument to make",
		      is_length ? "len" : "cap");
	  return false;
	case Numeric_constant::NC_UL_BIG:
	  // We don't want to give a compile-time error for a 64-bit
	  // value on a 32-bit target.
	  break;
	}

      mpz_t val;
      if (!nc.to_int(&val))
	go_unreachable();
      int bits = mpz_sizeinbase(val, 2);
      mpz_clear(val);
      Type* int_type = Type::lookup_integer_type("int");
      if (bits >= int_type->integer_type()->bits())
	{
	  go_error_at(e->location(), "%s argument too large for make",
		      is_length ? "len" : "cap");
	  return false;
	}

      *small = true;
      return true;
    }

  if (e->type()->integer_type() != NULL)
    {
      int ebits = e->type()->integer_type()->bits();
      int intbits = Type::lookup_integer_type("int")->integer_type()->bits();

      // We can treat ebits == intbits as small even for an unsigned
      // integer type, because we will convert the value to int and
      // then reject it in the runtime if it is negative.
      *small = ebits <= intbits;

      return true;
    }

  go_error_at(e->location(), "non-integer %s argument to make",
	      is_length ? "len" : "cap");
  return false;
}

// Return the type of the real or imag functions, given the type of
// the argument.  We need to map complex64 to float32 and complex128
// to float64, so it has to be done by name.  This returns NULL if it
// can't figure out the type.

Type*
Builtin_call_expression::real_imag_type(Type* arg_type)
{
  if (arg_type == NULL || arg_type->is_abstract())
    return NULL;
  Named_type* nt = arg_type->named_type();
  if (nt == NULL)
    return NULL;
  while (nt->real_type()->named_type() != NULL)
    nt = nt->real_type()->named_type();
  if (nt->name() == "complex64")
    return Type::lookup_float_type("float32");
  else if (nt->name() == "complex128")
    return Type::lookup_float_type("float64");
  else
    return NULL;
}

// Return the type of the complex function, given the type of one of the
// argments.  Like real_imag_type, we have to map by name.

Type*
Builtin_call_expression::complex_type(Type* arg_type)
{
  if (arg_type == NULL || arg_type->is_abstract())
    return NULL;
  Named_type* nt = arg_type->named_type();
  if (nt == NULL)
    return NULL;
  while (nt->real_type()->named_type() != NULL)
    nt = nt->real_type()->named_type();
  if (nt->name() == "float32")
    return Type::lookup_complex_type("complex64");
  else if (nt->name() == "float64")
    return Type::lookup_complex_type("complex128");
  else
    return NULL;
}

// Return a single argument, or NULL if there isn't one.

Expression*
Builtin_call_expression::one_arg() const
{
  const Expression_list* args = this->args();
  if (args == NULL || args->size() != 1)
    return NULL;
  return args->front();
}

// A traversal class which looks for a call or receive expression.

class Find_call_expression : public Traverse
{
 public:
  Find_call_expression()
    : Traverse(traverse_expressions),
      found_(false)
  { }

  int
  expression(Expression**);

  bool
  found()
  { return this->found_; }

 private:
  bool found_;
};

int
Find_call_expression::expression(Expression** pexpr)
{
  Expression* expr = *pexpr;
  if (!expr->is_constant()
      && (expr->call_expression() != NULL
	  || expr->receive_expression() != NULL))
    {
      this->found_ = true;
      return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Return whether calling len or cap on EXPR, of array type, is a
// constant.  The language spec says "the expressions len(s) and
// cap(s) are constants if the type of s is an array or pointer to an
// array and the expression s does not contain channel receives or
// (non-constant) function calls."

bool
Builtin_call_expression::array_len_is_constant(Expression* expr)
{
  go_assert(expr->type()->deref()->array_type() != NULL
	    && !expr->type()->deref()->is_slice_type());
  if (expr->is_constant())
    return true;
  Find_call_expression find_call;
  Expression::traverse(&expr, &find_call);
  return !find_call.found();
}

// Return whether this is constant: len of a string constant, or len
// or cap of an array, or unsafe.Sizeof, unsafe.Offsetof,
// unsafe.Alignof.

bool
Builtin_call_expression::do_is_constant() const
{
  if (this->is_error_expression())
    return true;
  switch (this->code_)
    {
    case BUILTIN_LEN:
    case BUILTIN_CAP:
      {
	if (this->seen_)
	  return false;

	Expression* arg = this->one_arg();
	if (arg == NULL)
	  return false;
	Type* arg_type = arg->type();
	if (arg_type->is_error())
	  return true;

	if (arg_type->points_to() != NULL
	    && arg_type->points_to()->array_type() != NULL
	    && !arg_type->points_to()->is_slice_type())
	  arg_type = arg_type->points_to();

	if (arg_type->array_type() != NULL
	    && arg_type->array_type()->length() != NULL)
          {
	    this->seen_ = true;
	    bool ret = Builtin_call_expression::array_len_is_constant(arg);
	    this->seen_ = false;
	    return ret;
          }

	if (this->code_ == BUILTIN_LEN && arg_type->is_string_type())
	  {
	    this->seen_ = true;
	    bool ret = arg->is_constant();
	    this->seen_ = false;
	    return ret;
	  }
      }
      break;

    case BUILTIN_SIZEOF:
    case BUILTIN_ALIGNOF:
      return this->one_arg() != NULL;

    case BUILTIN_OFFSETOF:
      {
	Expression* arg = this->one_arg();
	if (arg == NULL)
	  return false;
	return arg->field_reference_expression() != NULL;
      }

    case BUILTIN_COMPLEX:
      {
	const Expression_list* args = this->args();
	if (args != NULL && args->size() == 2)
	  return args->front()->is_constant() && args->back()->is_constant();
      }
      break;

    case BUILTIN_REAL:
    case BUILTIN_IMAG:
      {
	Expression* arg = this->one_arg();
	return arg != NULL && arg->is_constant();
      }

    default:
      break;
    }

  return false;
}

// Return a numeric constant if possible.

bool
Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
{
  if (this->code_ == BUILTIN_LEN
      || this->code_ == BUILTIN_CAP)
    {
      Expression* arg = this->one_arg();
      if (arg == NULL)
	return false;
      Type* arg_type = arg->type();
      if (arg_type->is_error())
	return false;

      if (this->code_ == BUILTIN_LEN && arg_type->is_string_type())
	{
	  std::string sval;
	  if (arg->string_constant_value(&sval))
	    {
	      nc->set_unsigned_long(Type::lookup_integer_type("int"),
				    sval.length());
	      return true;
	    }
	}

      if (arg_type->points_to() != NULL
	  && arg_type->points_to()->array_type() != NULL
	  && !arg_type->points_to()->is_slice_type())
	arg_type = arg_type->points_to();

      if (arg_type->array_type() != NULL
	  && arg_type->array_type()->length() != NULL)
	{
	  if (this->seen_)
	    return false;

	  // We may be replacing this expression with a constant
	  // during lowering, so verify the type to report any errors.
	  // It's OK to verify an array type more than once.
	  arg_type->verify();
	  if (!arg_type->is_error())
	    {
	      Expression* e = arg_type->array_type()->length();
	      this->seen_ = true;
	      bool r = e->numeric_constant_value(nc);
	      this->seen_ = false;
	      if (r)
		{
		  if (!nc->set_type(Type::lookup_integer_type("int"), false,
				    this->location()))
		    r = false;
		}
	      return r;
	    }
	}
    }
  else if (this->code_ == BUILTIN_SIZEOF
	   || this->code_ == BUILTIN_ALIGNOF)
    {
      Expression* arg = this->one_arg();
      if (arg == NULL)
	return false;
      Type* arg_type = arg->type();
      if (arg_type->is_error())
	return false;
      if (arg_type->is_abstract())
	arg_type = arg_type->make_non_abstract_type();
      if (this->seen_)
        return false;

      int64_t ret;
      if (this->code_ == BUILTIN_SIZEOF)
	{
          this->seen_ = true;
	  bool ok = arg_type->backend_type_size(this->gogo_, &ret);
          this->seen_ = false;
	  if (!ok)
	    return false;
	}
      else if (this->code_ == BUILTIN_ALIGNOF)
	{
	  bool ok;
          this->seen_ = true;
	  if (arg->field_reference_expression() == NULL)
	    ok = arg_type->backend_type_align(this->gogo_, &ret);
	  else
	    {
	      // Calling unsafe.Alignof(s.f) returns the alignment of
	      // the type of f when it is used as a field in a struct.
	      ok = arg_type->backend_type_field_align(this->gogo_, &ret);
	    }
          this->seen_ = false;
	  if (!ok)
	    return false;
	}
      else
	go_unreachable();

      mpz_t zval;
      set_mpz_from_int64(&zval, ret);
      nc->set_int(Type::lookup_integer_type("uintptr"), zval);
      mpz_clear(zval);
      return true;
    }
  else if (this->code_ == BUILTIN_OFFSETOF)
    {
      Expression* arg = this->one_arg();
      if (arg == NULL)
	return false;
      Field_reference_expression* farg = arg->field_reference_expression();
      if (farg == NULL)
	return false;
      if (this->seen_)
        return false;

      int64_t total_offset = 0;
      while (true)
        {
          Expression* struct_expr = farg->expr();
          Type* st = struct_expr->type();
          if (st->struct_type() == NULL)
            return false;
          if (st->named_type() != NULL)
            st->named_type()->convert(this->gogo_);
          if (st->is_error_type())
            {
              go_assert(saw_errors());
              return false;
            }
          int64_t offset;
          this->seen_ = true;
          bool ok = st->struct_type()->backend_field_offset(this->gogo_,
							    farg->field_index(),
							    &offset);
          this->seen_ = false;
	  if (!ok)
	    return false;
          total_offset += offset;
          if (farg->implicit() && struct_expr->field_reference_expression() != NULL)
            {
              // Go up until we reach the original base.
              farg = struct_expr->field_reference_expression();
              continue;
            }
          break;
        }
      mpz_t zval;
      set_mpz_from_int64(&zval, total_offset);
      nc->set_int(Type::lookup_integer_type("uintptr"), zval);
      mpz_clear(zval);
      return true;
    }
  else if (this->code_ == BUILTIN_REAL || this->code_ == BUILTIN_IMAG)
    {
      Expression* arg = this->one_arg();
      if (arg == NULL)
	return false;

      Numeric_constant argnc;
      if (!arg->numeric_constant_value(&argnc))
	return false;

      mpc_t val;
      if (!argnc.to_complex(&val))
	return false;

      Type* type = Builtin_call_expression::real_imag_type(argnc.type());
      if (this->code_ == BUILTIN_REAL)
	nc->set_float(type, mpc_realref(val));
      else
	nc->set_float(type, mpc_imagref(val));
      mpc_clear(val);
      return true;
    }
  else if (this->code_ == BUILTIN_COMPLEX)
    {
      const Expression_list* args = this->args();
      if (args == NULL || args->size() != 2)
	return false;

      Numeric_constant rnc;
      if (!args->front()->numeric_constant_value(&rnc))
	return false;
      Numeric_constant inc;
      if (!args->back()->numeric_constant_value(&inc))
	return false;

      if (rnc.type() != NULL
	  && !rnc.type()->is_abstract()
	  && inc.type() != NULL
	  && !inc.type()->is_abstract()
	  && !Type::are_identical(rnc.type(), inc.type(),
				  Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
				  NULL))
	return false;

      mpfr_t r;
      if (!rnc.to_float(&r))
	return false;
      mpfr_t i;
      if (!inc.to_float(&i))
	{
	  mpfr_clear(r);
	  return false;
	}

      Type* arg_type = rnc.type();
      if (arg_type == NULL || arg_type->is_abstract())
	arg_type = inc.type();

      mpc_t val;
      mpc_init2(val, mpc_precision);
      mpc_set_fr_fr(val, r, i, MPC_RNDNN);
      mpfr_clear(r);
      mpfr_clear(i);

      Type* type = Builtin_call_expression::complex_type(arg_type);
      nc->set_complex(type, val);

      mpc_clear(val);

      return true;
    }

  return false;
}

// Give an error if we are discarding the value of an expression which
// should not normally be discarded.  We don't give an error for
// discarding the value of an ordinary function call, but we do for
// builtin functions, purely for consistency with the gc compiler.

bool
Builtin_call_expression::do_discarding_value()
{
  switch (this->code_)
    {
    case BUILTIN_INVALID:
    default:
      go_unreachable();

    case BUILTIN_APPEND:
    case BUILTIN_CAP:
    case BUILTIN_COMPLEX:
    case BUILTIN_IMAG:
    case BUILTIN_LEN:
    case BUILTIN_MAKE:
    case BUILTIN_NEW:
    case BUILTIN_REAL:
    case BUILTIN_ALIGNOF:
    case BUILTIN_OFFSETOF:
    case BUILTIN_SIZEOF:
      this->unused_value_error();
      return false;

    case BUILTIN_CLOSE:
    case BUILTIN_COPY:
    case BUILTIN_DELETE:
    case BUILTIN_PANIC:
    case BUILTIN_PRINT:
    case BUILTIN_PRINTLN:
    case BUILTIN_RECOVER:
      return true;
    }
}

// Return the type.

Type*
Builtin_call_expression::do_type()
{
  if (this->is_error_expression())
    return Type::make_error_type();
  switch (this->code_)
    {
    case BUILTIN_INVALID:
    default:
      return Type::make_error_type();

    case BUILTIN_NEW:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->empty())
	  return Type::make_error_type();
	return Type::make_pointer_type(args->front()->type());
      }

    case BUILTIN_MAKE:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->empty())
	  return Type::make_error_type();
	return args->front()->type();
      }

    case BUILTIN_CAP:
    case BUILTIN_COPY:
    case BUILTIN_LEN:
      return Type::lookup_integer_type("int");

    case BUILTIN_ALIGNOF:
    case BUILTIN_OFFSETOF:
    case BUILTIN_SIZEOF:
      return Type::lookup_integer_type("uintptr");

    case BUILTIN_CLOSE:
    case BUILTIN_DELETE:
    case BUILTIN_PANIC:
    case BUILTIN_PRINT:
    case BUILTIN_PRINTLN:
      return Type::make_void_type();

    case BUILTIN_RECOVER:
      return Type::make_empty_interface_type(Linemap::predeclared_location());

    case BUILTIN_APPEND:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->empty())
	  return Type::make_error_type();
	Type *ret = args->front()->type();
	if (!ret->is_slice_type())
	  return Type::make_error_type();
	return ret;
      }

    case BUILTIN_REAL:
    case BUILTIN_IMAG:
      {
	Expression* arg = this->one_arg();
	if (arg == NULL)
	  return Type::make_error_type();
	Type* t = arg->type();
	if (t->is_abstract())
	  t = t->make_non_abstract_type();
	t = Builtin_call_expression::real_imag_type(t);
	if (t == NULL)
	  t = Type::make_error_type();
	return t;
      }

    case BUILTIN_COMPLEX:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->size() != 2)
	  return Type::make_error_type();
	Type* t = args->front()->type();
	if (t->is_abstract())
	  {
	    t = args->back()->type();
	    if (t->is_abstract())
	      t = t->make_non_abstract_type();
	  }
	t = Builtin_call_expression::complex_type(t);
	if (t == NULL)
	  t = Type::make_error_type();
	return t;
      }
    }
}

// Determine the type.

void
Builtin_call_expression::do_determine_type(const Type_context* context)
{
  if (!this->determining_types())
    return;

  this->fn()->determine_type_no_context();

  const Expression_list* args = this->args();

  bool is_print;
  Type* arg_type = NULL;
  Type* trailing_arg_types = NULL;
  switch (this->code_)
    {
    case BUILTIN_PRINT:
    case BUILTIN_PRINTLN:
      // Do not force a large integer constant to "int".
      is_print = true;
      break;

    case BUILTIN_REAL:
    case BUILTIN_IMAG:
      arg_type = Builtin_call_expression::complex_type(context->type);
      if (arg_type == NULL)
	arg_type = Type::lookup_complex_type("complex128");
      is_print = false;
      break;

    case BUILTIN_COMPLEX:
      {
	// For the complex function the type of one operand can
	// determine the type of the other, as in a binary expression.
	arg_type = Builtin_call_expression::real_imag_type(context->type);
	if (arg_type == NULL)
	  arg_type = Type::lookup_float_type("float64");
	if (args != NULL && args->size() == 2)
	  {
	    Type* t1 = args->front()->type();
	    Type* t2 = args->back()->type();
	    if (!t1->is_abstract())
	      arg_type = t1;
	    else if (!t2->is_abstract())
	      arg_type = t2;
	  }
	is_print = false;
      }
      break;

    case BUILTIN_APPEND:
      if (!this->is_varargs()
	  && args != NULL
	  && !args->empty()
	  && args->front()->type()->is_slice_type())
	trailing_arg_types =
	  args->front()->type()->array_type()->element_type();
      is_print = false;
      break;

    default:
      is_print = false;
      break;
    }

  if (args != NULL)
    {
      for (Expression_list::const_iterator pa = args->begin();
	   pa != args->end();
	   ++pa)
	{
	  Type_context subcontext;
	  subcontext.type = arg_type;

	  if (is_print)
	    {
	      // We want to print large constants, we so can't just
	      // use the appropriate nonabstract type.  Use uint64 for
	      // an integer if we know it is nonnegative, otherwise
	      // use int64 for a integer, otherwise use float64 for a
	      // float or complex128 for a complex.
	      Type* want_type = NULL;
	      Type* atype = (*pa)->type();
	      if (atype->is_abstract())
		{
		  if (atype->integer_type() != NULL)
		    {
		      Numeric_constant nc;
		      if (this->numeric_constant_value(&nc))
			{
			  mpz_t val;
			  if (nc.to_int(&val))
			    {
			      if (mpz_sgn(val) >= 0)
				want_type = Type::lookup_integer_type("uint64");
			      mpz_clear(val);
			    }
			}
		      if (want_type == NULL)
			want_type = Type::lookup_integer_type("int64");
		    }
		  else if (atype->float_type() != NULL)
		    want_type = Type::lookup_float_type("float64");
		  else if (atype->complex_type() != NULL)
		    want_type = Type::lookup_complex_type("complex128");
		  else if (atype->is_abstract_string_type())
		    want_type = Type::lookup_string_type();
		  else if (atype->is_abstract_boolean_type())
		    want_type = Type::lookup_bool_type();
		  else
		    go_unreachable();
		  subcontext.type = want_type;
		}
	    }

	  (*pa)->determine_type(&subcontext);

	  if (trailing_arg_types != NULL)
	    {
	      arg_type = trailing_arg_types;
	      trailing_arg_types = NULL;
	    }
	}
    }
}

// If there is exactly one argument, return true.  Otherwise give an
// error message and return false.

bool
Builtin_call_expression::check_one_arg()
{
  const Expression_list* args = this->args();
  if (args == NULL || args->size() < 1)
    {
      this->report_error(_("not enough arguments"));
      return false;
    }
  else if (args->size() > 1)
    {
      this->report_error(_("too many arguments"));
      return false;
    }
  if (args->front()->is_error_expression()
      || args->front()->type()->is_error())
    {
      this->set_is_error();
      return false;
    }
  return true;
}

// Check argument types for a builtin function.

void
Builtin_call_expression::do_check_types(Gogo*)
{
  if (this->is_error_expression())
    return;
  switch (this->code_)
    {
    case BUILTIN_INVALID:
    case BUILTIN_NEW:
    case BUILTIN_MAKE:
    case BUILTIN_DELETE:
      return;

    case BUILTIN_LEN:
    case BUILTIN_CAP:
      {
	// The single argument may be either a string or an array or a
	// map or a channel, or a pointer to a closed array.
	if (this->check_one_arg())
	  {
	    Type* arg_type = this->one_arg()->type();
	    if (arg_type->points_to() != NULL
		&& arg_type->points_to()->array_type() != NULL
		&& !arg_type->points_to()->is_slice_type())
	      arg_type = arg_type->points_to();
	    if (this->code_ == BUILTIN_CAP)
	      {
		if (!arg_type->is_error()
		    && arg_type->array_type() == NULL
		    && arg_type->channel_type() == NULL)
		  this->report_error(_("argument must be array or slice "
				       "or channel"));
	      }
	    else
	      {
		if (!arg_type->is_error()
		    && !arg_type->is_string_type()
		    && arg_type->array_type() == NULL
		    && arg_type->map_type() == NULL
		    && arg_type->channel_type() == NULL)
		  this->report_error(_("argument must be string or "
				       "array or slice or map or channel"));
	      }
	  }
      }
      break;

    case BUILTIN_PRINT:
    case BUILTIN_PRINTLN:
      {
	const Expression_list* args = this->args();
	if (args == NULL)
	  {
	    if (this->code_ == BUILTIN_PRINT)
	      go_warning_at(this->location(), 0,
			 "no arguments for built-in function %<%s%>",
			 (this->code_ == BUILTIN_PRINT
			  ? "print"
			  : "println"));
	  }
	else
	  {
	    for (Expression_list::const_iterator p = args->begin();
		 p != args->end();
		 ++p)
	      {
		Type* type = (*p)->type();
		if (type->is_error()
		    || type->is_string_type()
		    || type->integer_type() != NULL
		    || type->float_type() != NULL
		    || type->complex_type() != NULL
		    || type->is_boolean_type()
		    || type->points_to() != NULL
		    || type->interface_type() != NULL
		    || type->channel_type() != NULL
		    || type->map_type() != NULL
		    || type->function_type() != NULL
		    || type->is_slice_type())
		  ;
		else if ((*p)->is_type_expression())
		  {
		    // If this is a type expression it's going to give
		    // an error anyhow, so we don't need one here.
		  }
		else
		  this->report_error(_("unsupported argument type to "
				       "builtin function"));
	      }
	  }
      }
      break;

    case BUILTIN_CLOSE:
      if (this->check_one_arg())
	{
	  if (this->one_arg()->type()->channel_type() == NULL)
	    this->report_error(_("argument must be channel"));
	  else if (!this->one_arg()->type()->channel_type()->may_send())
	    this->report_error(_("cannot close receive-only channel"));
	}
      break;

    case BUILTIN_PANIC:
    case BUILTIN_SIZEOF:
    case BUILTIN_ALIGNOF:
      this->check_one_arg();
      break;

    case BUILTIN_RECOVER:
      if (this->args() != NULL
	  && !this->args()->empty()
	  && !this->recover_arg_is_set_)
	this->report_error(_("too many arguments"));
      break;

    case BUILTIN_OFFSETOF:
      if (this->check_one_arg())
	{
	  Expression* arg = this->one_arg();
	  if (arg->field_reference_expression() == NULL)
	    this->report_error(_("argument must be a field reference"));
	}
      break;

    case BUILTIN_COPY:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->size() < 2)
	  {
	    this->report_error(_("not enough arguments"));
	    break;
	  }
	else if (args->size() > 2)
	  {
	    this->report_error(_("too many arguments"));
	    break;
	  }
	Type* arg1_type = args->front()->type();
	Type* arg2_type = args->back()->type();
	if (arg1_type->is_error() || arg2_type->is_error())
	  {
	    this->set_is_error();
	    break;
	  }

	Type* e1;
	if (arg1_type->is_slice_type())
	  e1 = arg1_type->array_type()->element_type();
	else
	  {
	    this->report_error(_("left argument must be a slice"));
	    break;
	  }

	if (arg2_type->is_slice_type())
	  {
	    Type* e2 = arg2_type->array_type()->element_type();
	    if (!Type::are_identical(e1, e2, Type::COMPARE_TAGS, NULL))
	      this->report_error(_("element types must be the same"));
	  }
	else if (arg2_type->is_string_type())
	  {
	    if (e1->integer_type() == NULL || !e1->integer_type()->is_byte())
	      this->report_error(_("first argument must be []byte"));
	  }
	else
	    this->report_error(_("second argument must be slice or string"));
      }
      break;

    case BUILTIN_APPEND:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->empty())
	  {
	    this->report_error(_("not enough arguments"));
	    break;
	  }

	Type* slice_type = args->front()->type();
	if (!slice_type->is_slice_type())
	  {
	    if (slice_type->is_error_type())
	      break;
	    if (slice_type->is_nil_type())
	      go_error_at(args->front()->location(), "use of untyped nil");
	    else
	      go_error_at(args->front()->location(),
			  "argument 1 must be a slice");
	    this->set_is_error();
	    break;
	  }

	Type* element_type = slice_type->array_type()->element_type();
	if (!element_type->in_heap())
	  go_error_at(args->front()->location(),
		      "cannot append to slice of go:notinheap type");
	if (this->is_varargs())
	  {
	    if (!args->back()->type()->is_slice_type()
		&& !args->back()->type()->is_string_type())
	      {
		go_error_at(args->back()->location(),
			    "invalid use of %<...%> with non-slice/non-string");
		this->set_is_error();
		break;
	      }

	    if (args->size() < 2)
	      {
		this->report_error(_("not enough arguments"));
		break;
	      }
	    if (args->size() > 2)
	      {
		this->report_error(_("too many arguments"));
		break;
	      }

	    if (args->back()->type()->is_string_type()
		&& element_type->integer_type() != NULL
		&& element_type->integer_type()->is_byte())
	      {
		// Permit append(s1, s2...) when s1 is a slice of
		// bytes and s2 is a string type.
	      }
	    else
	      {
		// We have to test for assignment compatibility to a
		// slice of the element type, which is not necessarily
		// the same as the type of the first argument: the
		// first argument might have a named type.
		Type* check_type = Type::make_array_type(element_type, NULL);
		std::string reason;
		if (!Type::are_assignable(check_type, args->back()->type(),
					  &reason))
		  {
		    if (reason.empty())
		      go_error_at(args->back()->location(),
				  "argument 2 has invalid type");
		    else
		      go_error_at(args->back()->location(),
				  "argument 2 has invalid type (%s)",
				  reason.c_str());
		    this->set_is_error();
		    break;
		  }
	      }
	  }
	else
	  {
	    Expression_list::const_iterator pa = args->begin();
	    int i = 2;
	    for (++pa; pa != args->end(); ++pa, ++i)
	      {
		std::string reason;
		if (!Type::are_assignable(element_type, (*pa)->type(),
					  &reason))
		  {
		    if (reason.empty())
		      go_error_at((*pa)->location(),
				  "argument %d has incompatible type", i);
		    else
		      go_error_at((*pa)->location(),
				  "argument %d has incompatible type (%s)",
				  i, reason.c_str());
		    this->set_is_error();
		  }
	      }
	  }
      }
      break;

    case BUILTIN_REAL:
    case BUILTIN_IMAG:
      if (this->check_one_arg())
	{
	  if (this->one_arg()->type()->complex_type() == NULL)
	    this->report_error(_("argument must have complex type"));
	}
      break;

    case BUILTIN_COMPLEX:
      {
	const Expression_list* args = this->args();
	if (args == NULL || args->size() < 2)
	  this->report_error(_("not enough arguments"));
	else if (args->size() > 2)
	  this->report_error(_("too many arguments"));
	else if (args->front()->is_error_expression()
		 || args->front()->type()->is_error()
		 || args->back()->is_error_expression()
		 || args->back()->type()->is_error())
	  this->set_is_error();
	else if (!Type::are_identical(args->front()->type(),
				      args->back()->type(),
				      Type::COMPARE_TAGS, NULL))
	  this->report_error(_("complex arguments must have identical types"));
	else if (args->front()->type()->float_type() == NULL)
	  this->report_error(_("complex arguments must have "
			       "floating-point type"));
      }
      break;

    default:
      go_unreachable();
    }
}

Expression*
Builtin_call_expression::do_copy()
{
  Call_expression* bce =
    new Builtin_call_expression(this->gogo_, this->fn()->copy(),
				(this->args() == NULL
				 ? NULL
				 : this->args()->copy()),
				this->is_varargs(),
				this->location());

  if (this->varargs_are_lowered())
    bce->set_varargs_are_lowered();
  if (this->is_deferred())
    bce->set_is_deferred();
  if (this->is_concurrent())
    bce->set_is_concurrent();
  return bce;
}

// Return the backend representation for a builtin function.

Bexpression*
Builtin_call_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Location location = this->location();

  if (this->is_erroneous_call())
    {
      go_assert(saw_errors());
      return gogo->backend()->error_expression();
    }

  switch (this->code_)
    {
    case BUILTIN_INVALID:
    case BUILTIN_NEW:
    case BUILTIN_MAKE:
      go_unreachable();

    case BUILTIN_LEN:
    case BUILTIN_CAP:
      {
	const Expression_list* args = this->args();
	go_assert(args != NULL && args->size() == 1);
	Expression* arg = args->front();
	Type* arg_type = arg->type();

	if (this->seen_)
	  {
	    go_assert(saw_errors());
	    return context->backend()->error_expression();
	  }
	this->seen_ = true;
	this->seen_ = false;
	if (arg_type->points_to() != NULL)
	  {
	    arg_type = arg_type->points_to();
	    go_assert(arg_type->array_type() != NULL
		       && !arg_type->is_slice_type());
            arg = Expression::make_dereference(arg, NIL_CHECK_DEFAULT,
                                               location);
	  }

	Type* int_type = Type::lookup_integer_type("int");
        Expression* val;
	if (this->code_ == BUILTIN_LEN)
	  {
	    if (arg_type->is_string_type())
	      val = Expression::make_string_info(arg, STRING_INFO_LENGTH,
						 location);
	    else if (arg_type->array_type() != NULL)
	      {
		if (this->seen_)
		  {
		    go_assert(saw_errors());
		    return context->backend()->error_expression();
		  }
		this->seen_ = true;
	        val = arg_type->array_type()->get_length(gogo, arg);
		this->seen_ = false;
	      }
	    else if (arg_type->map_type() != NULL
		     || arg_type->channel_type() != NULL)
	      {
		// The first field is the length.  If the pointer is
		// nil, the length is zero.
		Type* pint_type = Type::make_pointer_type(int_type);
		arg = Expression::make_unsafe_cast(pint_type, arg, location);
		Expression* nil = Expression::make_nil(location);
		nil = Expression::make_cast(pint_type, nil, location);
		Expression* cmp = Expression::make_binary(OPERATOR_EQEQ,
							  arg, nil, location);
		Expression* zero = Expression::make_integer_ul(0, int_type,
							       location);
                Expression* indir =
                    Expression::make_dereference(arg, NIL_CHECK_NOT_NEEDED,
                                                 location);
		val = Expression::make_conditional(cmp, zero, indir, location);
	      }
	    else
	      go_unreachable();
	  }
	else
	  {
	    if (arg_type->array_type() != NULL)
	      {
		if (this->seen_)
		  {
		    go_assert(saw_errors());
		    return context->backend()->error_expression();
		  }
		this->seen_ = true;
                val = arg_type->array_type()->get_capacity(gogo, arg);
		this->seen_ = false;
	      }
	    else if (arg_type->channel_type() != NULL)
	      {
		// The second field is the capacity.  If the pointer
		// is nil, the capacity is zero.
		Type* uintptr_type = Type::lookup_integer_type("uintptr");
		Type* pint_type = Type::make_pointer_type(int_type);
		Expression* parg = Expression::make_unsafe_cast(uintptr_type,
								arg,
								location);
		int off = int_type->integer_type()->bits() / 8;
		Expression* eoff = Expression::make_integer_ul(off,
							       uintptr_type,
							       location);
		parg = Expression::make_binary(OPERATOR_PLUS, parg, eoff,
					       location);
		parg = Expression::make_unsafe_cast(pint_type, parg, location);
		Expression* nil = Expression::make_nil(location);
		nil = Expression::make_cast(pint_type, nil, location);
		Expression* cmp = Expression::make_binary(OPERATOR_EQEQ,
							  arg, nil, location);
		Expression* zero = Expression::make_integer_ul(0, int_type,
							       location);
                Expression* indir =
                    Expression::make_dereference(parg, NIL_CHECK_NOT_NEEDED,
                                                 location);
		val = Expression::make_conditional(cmp, zero, indir, location);
	      }
	    else
	      go_unreachable();
	  }

	return Expression::make_cast(int_type, val,
				     location)->get_backend(context);
      }

    case BUILTIN_PRINT:
    case BUILTIN_PRINTLN:
      {
	const bool is_ln = this->code_ == BUILTIN_PRINTLN;

	Expression* print_stmts = Runtime::make_call(Runtime::PRINTLOCK,
						     location, 0);

	const Expression_list* call_args = this->args();
	if (call_args != NULL)
	  {
	    for (Expression_list::const_iterator p = call_args->begin();
		 p != call_args->end();
		 ++p)
	      {
		if (is_ln && p != call_args->begin())
		  {
                    Expression* print_space =
		      Runtime::make_call(Runtime::PRINTSP, location, 0);

                    print_stmts =
                        Expression::make_compound(print_stmts, print_space,
                                                  location);
		  }

                Expression* arg = *p;
		Type* type = arg->type();
                Runtime::Function code;
		if (type->is_string_type())
                  code = Runtime::PRINTSTRING;
		else if (type->integer_type() != NULL
			 && type->integer_type()->is_unsigned())
		  {
		    Type* itype = Type::lookup_integer_type("uint64");
		    arg = Expression::make_cast(itype, arg, location);
                    if (gogo->compiling_runtime()
                        && type->named_type() != NULL
                        && gogo->unpack_hidden_name(type->named_type()->name())
                           == "hex")
                      code = Runtime::PRINTHEX;
                    else
                      code = Runtime::PRINTUINT;
		  }
		else if (type->integer_type() != NULL)
		  {
		    Type* itype = Type::lookup_integer_type("int64");
		    arg = Expression::make_cast(itype, arg, location);
                    code = Runtime::PRINTINT;
		  }
		else if (type->float_type() != NULL)
		  {
                    Type* dtype = Type::lookup_float_type("float64");
                    arg = Expression::make_cast(dtype, arg, location);
                    code = Runtime::PRINTFLOAT;
		  }
		else if (type->complex_type() != NULL)
		  {
                    Type* ctype = Type::lookup_complex_type("complex128");
                    arg = Expression::make_cast(ctype, arg, location);
                    code = Runtime::PRINTCOMPLEX;
		  }
		else if (type->is_boolean_type())
                  code = Runtime::PRINTBOOL;
		else if (type->points_to() != NULL
			 || type->channel_type() != NULL
			 || type->map_type() != NULL
			 || type->function_type() != NULL)
		  {
                    arg = Expression::make_cast(type, arg, location);
                    code = Runtime::PRINTPOINTER;
		  }
		else if (type->interface_type() != NULL)
		  {
		    if (type->interface_type()->is_empty())
                      code = Runtime::PRINTEFACE;
		    else
                      code = Runtime::PRINTIFACE;
		  }
		else if (type->is_slice_type())
                  code = Runtime::PRINTSLICE;
		else
		  {
		    go_assert(saw_errors());
		    return context->backend()->error_expression();
		  }

                Expression* call = Runtime::make_call(code, location, 1, arg);
		print_stmts = Expression::make_compound(print_stmts, call,
							location);
	      }
	  }

	if (is_ln)
	  {
            Expression* print_nl =
                Runtime::make_call(Runtime::PRINTNL, location, 0);
	    print_stmts = Expression::make_compound(print_stmts, print_nl,
						    location);
	  }

	Expression* unlock = Runtime::make_call(Runtime::PRINTUNLOCK,
						location, 0);
	print_stmts = Expression::make_compound(print_stmts, unlock, location);

        return print_stmts->get_backend(context);
      }

    case BUILTIN_PANIC:
      {
	const Expression_list* args = this->args();
	go_assert(args != NULL && args->size() == 1);
	Expression* arg = args->front();
	Type *empty =
	  Type::make_empty_interface_type(Linemap::predeclared_location());
        arg = Expression::convert_for_assignment(gogo, empty, arg, location);

        Expression* panic =
            Runtime::make_call(Runtime::GOPANIC, location, 1, arg);
        return panic->get_backend(context);
      }

    case BUILTIN_RECOVER:
      {
	// The argument is set when building recover thunks.  It's a
	// boolean value which is true if we can recover a value now.
	const Expression_list* args = this->args();
	go_assert(args != NULL && args->size() == 1);
	Expression* arg = args->front();
	Type *empty =
	  Type::make_empty_interface_type(Linemap::predeclared_location());

	Expression* nil = Expression::make_nil(location);
        nil = Expression::make_interface_value(empty, nil, nil, location);

	// We need to handle a deferred call to recover specially,
	// because it changes whether it can recover a panic or not.
	// See test7 in test/recover1.go.
        Expression* recover = Runtime::make_call((this->is_deferred()
                                                  ? Runtime::DEFERREDRECOVER
                                                  : Runtime::GORECOVER),
                                                 location, 0);
        Expression* cond =
            Expression::make_conditional(arg, recover, nil, location);
        return cond->get_backend(context);
      }

    case BUILTIN_CLOSE:
      {
	const Expression_list* args = this->args();
	go_assert(args != NULL && args->size() == 1);
	Expression* arg = args->front();
        Expression* close = Runtime::make_call(Runtime::CLOSE, location,
					       1, arg);
        return close->get_backend(context);
      }

    case BUILTIN_SIZEOF:
    case BUILTIN_OFFSETOF:
    case BUILTIN_ALIGNOF:
      {
	Numeric_constant nc;
	unsigned long val;
	if (!this->numeric_constant_value(&nc)
	    || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
	  {
	    go_assert(saw_errors());
	    return context->backend()->error_expression();
	  }
	Type* uintptr_type = Type::lookup_integer_type("uintptr");
        mpz_t ival;
        nc.get_int(&ival);
        Expression* int_cst =
            Expression::make_integer_z(&ival, uintptr_type, location);
        mpz_clear(ival);
        return int_cst->get_backend(context);
      }

    case BUILTIN_COPY:
      // Handled in Builtin_call_expression::do_flatten.
      go_unreachable();

    case BUILTIN_APPEND:
      // Handled in Builtin_call_expression::flatten_append.
      go_unreachable();

    case BUILTIN_REAL:
    case BUILTIN_IMAG:
      {
	const Expression_list* args = this->args();
	go_assert(args != NULL && args->size() == 1);

        Bexpression* ret;
        Bexpression* bcomplex = args->front()->get_backend(context);
        if (this->code_ == BUILTIN_REAL)
          ret = gogo->backend()->real_part_expression(bcomplex, location);
        else
          ret = gogo->backend()->imag_part_expression(bcomplex, location);
        return ret;
      }

    case BUILTIN_COMPLEX:
      {
	const Expression_list* args = this->args();
	go_assert(args != NULL && args->size() == 2);
	Bexpression* breal = args->front()->get_backend(context);
	Bexpression* bimag = args->back()->get_backend(context);
	return gogo->backend()->complex_expression(breal, bimag, location);
      }

    default:
      go_unreachable();
    }
}

// We have to support exporting a builtin call expression, because
// code can set a constant to the result of a builtin expression.

void
Builtin_call_expression::do_export(Export_function_body* efb) const
{
  Numeric_constant nc;
  if (this->numeric_constant_value(&nc))
    {
      if (nc.is_int())
	{
	  mpz_t val;
	  nc.get_int(&val);
	  Integer_expression::export_integer(efb, val);
	  mpz_clear(val);
	}
      else if (nc.is_float())
	{
	  mpfr_t fval;
	  nc.get_float(&fval);
	  Float_expression::export_float(efb, fval);
	  mpfr_clear(fval);
	}
      else if (nc.is_complex())
	{
	  mpc_t cval;
	  nc.get_complex(&cval);
	  Complex_expression::export_complex(efb, cval);
	  mpc_clear(cval);
	}
      else
	go_unreachable();

      // A trailing space lets us reliably identify the end of the number.
      efb->write_c_string(" ");
    }
  else
    {
      const char *s = NULL;
      switch (this->code_)
	{
	default:
	  go_unreachable();
	case BUILTIN_APPEND:
	  s = "append";
	  break;
	case BUILTIN_COPY:
	  s = "copy";
	  break;
	case BUILTIN_LEN:
	  s = "len";
	  break;
	case BUILTIN_CAP:
	  s = "cap";
	  break;
	case BUILTIN_DELETE:
	  s = "delete";
	  break;
	case BUILTIN_PRINT:
	  s = "print";
	  break;
	case BUILTIN_PRINTLN:
	  s = "println";
	  break;
	case BUILTIN_PANIC:
	  s = "panic";
	  break;
	case BUILTIN_RECOVER:
	  s = "recover";
	  break;
	case BUILTIN_CLOSE:
	  s = "close";
	  break;
	case BUILTIN_REAL:
	  s = "real";
	  break;
	case BUILTIN_IMAG:
	  s = "imag";
	  break;
	case BUILTIN_COMPLEX:
	  s = "complex";
	  break;
	}
      efb->write_c_string(s);
      this->export_arguments(efb);
    }
}

// Class Call_expression.

// A Go function can be viewed in a couple of different ways.  The
// code of a Go function becomes a backend function with parameters
// whose types are simply the backend representation of the Go types.
// If there are multiple results, they are returned as a backend
// struct.

// However, when Go code refers to a function other than simply
// calling it, the backend type of that function is actually a struct.
// The first field of the struct points to the Go function code
// (sometimes a wrapper as described below).  The remaining fields
// hold addresses of closed-over variables.  This struct is called a
// closure.

// There are a few cases to consider.

// A direct function call of a known function in package scope.  In
// this case there are no closed-over variables, and we know the name
// of the function code.  We can simply produce a backend call to the
// function directly, and not worry about the closure.

// A direct function call of a known function literal.  In this case
// we know the function code and we know the closure.  We generate the
// function code such that it expects an additional final argument of
// the closure type.  We pass the closure as the last argument, after
// the other arguments.

// An indirect function call.  In this case we have a closure.  We
// load the pointer to the function code from the first field of the
// closure.  We pass the address of the closure as the last argument.

// A call to a method of an interface.  Type methods are always at
// package scope, so we call the function directly, and don't worry
// about the closure.

// This means that for a function at package scope we have two cases.
// One is the direct call, which has no closure.  The other is the
// indirect call, which does have a closure.  We can't simply ignore
// the closure, even though it is the last argument, because that will
// fail on targets where the function pops its arguments.  So when
// generating a closure for a package-scope function we set the
// function code pointer in the closure to point to a wrapper
// function.  This wrapper function accepts a final argument that
// points to the closure, ignores it, and calls the real function as a
// direct function call.  This wrapper will normally be efficient, and
// can often simply be a tail call to the real function.

// We don't use GCC's static chain pointer because 1) we don't need
// it; 2) GCC only permits using a static chain to call a known
// function, so we can't use it for an indirect call anyhow.  Since we
// can't use it for an indirect call, we may as well not worry about
// using it for a direct call either.

// We pass the closure last rather than first because it means that
// the function wrapper we put into a closure for a package-scope
// function can normally just be a tail call to the real function.

// For method expressions we generate a wrapper that loads the
// receiver from the closure and then calls the method.  This
// unfortunately forces reshuffling the arguments, since there is a
// new first argument, but we can't avoid reshuffling either for
// method expressions or for indirect calls of package-scope
// functions, and since the latter are more common we reshuffle for
// method expressions.

// Note that the Go code retains the Go types.  The extra final
// argument only appears when we convert to the backend
// representation.

// Traversal.

int
Call_expression::do_traverse(Traverse* traverse)
{
  // If we are calling a function in a different package that returns
  // an unnamed type, this may be the only chance we get to traverse
  // that type.  We don't traverse this->type_ because it may be a
  // Call_multiple_result_type that will just lead back here.
  if (this->type_ != NULL && !this->type_->is_error_type())
    {
      Function_type *fntype = this->get_function_type();
      if (fntype != NULL && Type::traverse(fntype, traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  if (Expression::traverse(&this->fn_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->args_ != NULL)
    {
      if (this->args_->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Lower a call statement.

Expression*
Call_expression::do_lower(Gogo* gogo, Named_object* function,
			  Statement_inserter* inserter, int)
{
  Location loc = this->location();

  // A type cast can look like a function call.
  if (this->fn_->is_type_expression()
      && this->args_ != NULL
      && this->args_->size() == 1)
    return Expression::make_cast(this->fn_->type(), this->args_->front(),
				 loc);

  // Because do_type will return an error type and thus prevent future
  // errors, check for that case now to ensure that the error gets
  // reported.
  Function_type* fntype = this->get_function_type();
  if (fntype == NULL)
    {
      if (!this->fn_->type()->is_error())
	this->report_error(_("expected function"));
      this->set_is_error();
      return this;
    }

  // Handle an argument which is a call to a function which returns
  // multiple results.
  if (this->args_ != NULL
      && this->args_->size() == 1
      && this->args_->front()->call_expression() != NULL)
    {
      size_t rc = this->args_->front()->call_expression()->result_count();
      if (rc > 1
	  && ((fntype->parameters() != NULL
               && (fntype->parameters()->size() == rc
                   || (fntype->is_varargs()
                       && fntype->parameters()->size() - 1 <= rc)))
              || fntype->is_builtin()))
	{
	  Call_expression* call = this->args_->front()->call_expression();
	  call->set_is_multi_value_arg();
	  if (this->is_varargs_)
	    {
	      // It is not clear which result of a multiple result call
	      // the ellipsis operator should be applied to.  If we unpack the
	      // the call into its individual results here, the ellipsis will be
	      // applied to the last result.
	      go_error_at(call->location(),
			  _("multiple-value argument in single-value context"));
	      return Expression::make_error(call->location());
	    }

	  Expression_list* args = new Expression_list;
	  for (size_t i = 0; i < rc; ++i)
	    args->push_back(Expression::make_call_result(call, i));
	  // We can't return a new call expression here, because this
	  // one may be referenced by Call_result expressions.  We
	  // also can't delete the old arguments, because we may still
	  // traverse them somewhere up the call stack.  FIXME.
	  this->args_ = args;
	}
    }

  // Recognize a call to a builtin function.
  if (fntype->is_builtin())
    {
      Builtin_call_expression* bce =
	new Builtin_call_expression(gogo, this->fn_, this->args_,
				    this->is_varargs_, loc);
      if (this->is_deferred_)
	bce->set_is_deferred();
      if (this->is_concurrent_)
	bce->set_is_concurrent();
      return bce;
    }

  // If this call returns multiple results, create a temporary
  // variable to hold them.
  if (this->result_count() > 1 && this->call_temp_ == NULL)
    {
      Struct_field_list* sfl = new Struct_field_list();
      const Typed_identifier_list* results = fntype->results();

      int i = 0;
      char buf[20];
      for (Typed_identifier_list::const_iterator p = results->begin();
           p != results->end();
           ++p, ++i)
        {
          snprintf(buf, sizeof buf, "res%d", i);
          sfl->push_back(Struct_field(Typed_identifier(buf, p->type(), loc)));
        }

      Struct_type* st = Type::make_struct_type(sfl, loc);
      st->set_is_struct_incomparable();
      this->call_temp_ = Statement::make_temporary(st, NULL, loc);
      inserter->insert(this->call_temp_);
    }

  // Handle a call to a varargs function by packaging up the extra
  // parameters.
  if (fntype->is_varargs())
    {
      const Typed_identifier_list* parameters = fntype->parameters();
      go_assert(parameters != NULL && !parameters->empty());
      Type* varargs_type = parameters->back().type();
      this->lower_varargs(gogo, function, inserter, varargs_type,
			  parameters->size(), SLICE_STORAGE_MAY_ESCAPE);
    }

  // If this is call to a method, call the method directly passing the
  // object as the first parameter.
  Bound_method_expression* bme = this->fn_->bound_method_expression();
  if (bme != NULL && !this->is_deferred_ && !this->is_concurrent_)
    {
      Named_object* methodfn = bme->function();
      Function_type* mft = (methodfn->is_function()
                            ? methodfn->func_value()->type()
                            : methodfn->func_declaration_value()->type());
      Expression* first_arg = bme->first_argument();

      // We always pass a pointer when calling a method, except for
      // direct interface types when calling a value method.
      if (!first_arg->type()->is_error()
          && !first_arg->type()->is_direct_iface_type())
	{
	  first_arg = Expression::make_unary(OPERATOR_AND, first_arg, loc);
	  // We may need to create a temporary variable so that we can
	  // take the address.  We can't do that here because it will
	  // mess up the order of evaluation.
	  Unary_expression* ue = static_cast<Unary_expression*>(first_arg);
	  ue->set_create_temp();
	}
      else if (mft->receiver()->type()->points_to() == NULL
               && first_arg->type()->points_to() != NULL
               && first_arg->type()->points_to()->is_direct_iface_type())
        first_arg = Expression::make_dereference(first_arg,
                                                 Expression::NIL_CHECK_DEFAULT,
                                                 loc);

      // If we are calling a method which was inherited from an
      // embedded struct, and the method did not get a stub, then the
      // first type may be wrong.
      Type* fatype = bme->first_argument_type();
      if (fatype != NULL)
	{
	  if (fatype->points_to() == NULL)
	    fatype = Type::make_pointer_type(fatype);
	  first_arg = Expression::make_unsafe_cast(fatype, first_arg, loc);
	}

      Expression_list* new_args = new Expression_list();
      new_args->push_back(first_arg);
      if (this->args_ != NULL)
	{
	  for (Expression_list::const_iterator p = this->args_->begin();
	       p != this->args_->end();
	       ++p)
	    new_args->push_back(*p);
	}

      // We have to change in place because this structure may be
      // referenced by Call_result_expressions.  We can't delete the
      // old arguments, because we may be traversing them up in some
      // caller.  FIXME.
      this->args_ = new_args;
      this->fn_ = Expression::make_func_reference(methodfn, NULL,
						  bme->location());
    }

  // If this is a call to an imported function for which we have an
  // inlinable function body, add it to the list of functions to give
  // to the backend as inlining opportunities.
  Func_expression* fe = this->fn_->func_expression();
  if (fe != NULL
      && fe->named_object()->is_function_declaration()
      && fe->named_object()->func_declaration_value()->has_imported_body())
    gogo->add_imported_inlinable_function(fe->named_object());

  return this;
}

// Lower a call to a varargs function.  FUNCTION is the function in
// which the call occurs--it's not the function we are calling.
// VARARGS_TYPE is the type of the varargs parameter, a slice type.
// PARAM_COUNT is the number of parameters of the function we are
// calling; the last of these parameters will be the varargs
// parameter.

void
Call_expression::lower_varargs(Gogo* gogo, Named_object* function,
			       Statement_inserter* inserter,
			       Type* varargs_type, size_t param_count,
                               Slice_storage_escape_disp escape_disp)
{
  if (this->varargs_are_lowered_)
    return;

  Location loc = this->location();

  go_assert(param_count > 0);
  go_assert(varargs_type->is_slice_type());

  size_t arg_count = this->args_ == NULL ? 0 : this->args_->size();
  if (arg_count < param_count - 1)
    {
      // Not enough arguments; will be caught in check_types.
      return;
    }

  Expression_list* old_args = this->args_;
  Expression_list* new_args = new Expression_list();
  bool push_empty_arg = false;
  if (old_args == NULL || old_args->empty())
    {
      go_assert(param_count == 1);
      push_empty_arg = true;
    }
  else
    {
      Expression_list::const_iterator pa;
      int i = 1;
      for (pa = old_args->begin(); pa != old_args->end(); ++pa, ++i)
	{
	  if (static_cast<size_t>(i) == param_count)
	    break;
	  new_args->push_back(*pa);
	}

      // We have reached the varargs parameter.

      bool issued_error = false;
      if (pa == old_args->end())
	push_empty_arg = true;
      else if (pa + 1 == old_args->end() && this->is_varargs_)
	new_args->push_back(*pa);
      else if (this->is_varargs_)
	{
	  if ((*pa)->type()->is_slice_type())
	    this->report_error(_("too many arguments"));
	  else
	    {
	      go_error_at(this->location(),
			  _("invalid use of %<...%> with non-slice"));
	      this->set_is_error();
	    }
	  return;
	}
      else
	{
	  Type* element_type = varargs_type->array_type()->element_type();
	  Expression_list* vals = new Expression_list;
	  for (; pa != old_args->end(); ++pa, ++i)
	    {
	      // Check types here so that we get a better message.
	      Type* patype = (*pa)->type();
	      Location paloc = (*pa)->location();
	      if (!this->check_argument_type(i, element_type, patype,
					     paloc, issued_error))
		continue;
	      vals->push_back(*pa);
	    }
	  Slice_construction_expression* sce =
	    Expression::make_slice_composite_literal(varargs_type, vals, loc);
	  if (escape_disp == SLICE_STORAGE_DOES_NOT_ESCAPE)
	      sce->set_storage_does_not_escape();
          Expression* val = sce;
	  gogo->lower_expression(function, inserter, &val);
	  new_args->push_back(val);
	}
    }

  if (push_empty_arg)
    new_args->push_back(Expression::make_nil(loc));

  // We can't return a new call expression here, because this one may
  // be referenced by Call_result expressions.  FIXME.  We can't
  // delete OLD_ARGS because we may have both a Call_expression and a
  // Builtin_call_expression which refer to them.  FIXME.
  this->args_ = new_args;
  this->varargs_are_lowered_ = true;
}

// Flatten a call with multiple results into a temporary.

Expression*
Call_expression::do_flatten(Gogo* gogo, Named_object*,
			    Statement_inserter* inserter)
{
  if (this->is_erroneous_call())
    {
      go_assert(saw_errors());
      return Expression::make_error(this->location());
    }

  if (this->is_flattened_)
    return this;
  this->is_flattened_ = true;

  // Add temporary variables for all arguments that require type
  // conversion.
  Function_type* fntype = this->get_function_type();
  if (fntype == NULL)
    {
      go_assert(saw_errors());
      return this;
    }
  if (this->args_ != NULL && !this->args_->empty()
      && fntype->parameters() != NULL && !fntype->parameters()->empty())
    {
      bool is_interface_method =
	this->fn_->interface_field_reference_expression() != NULL;

      Expression_list *args = new Expression_list();
      Typed_identifier_list::const_iterator pp = fntype->parameters()->begin();
      Expression_list::const_iterator pa = this->args_->begin();
      if (!is_interface_method && fntype->is_method())
	{
	  // The receiver argument.
	  args->push_back(*pa);
	  ++pa;
	}
      for (; pa != this->args_->end(); ++pa, ++pp)
	{
	  go_assert(pp != fntype->parameters()->end());
	  if (Type::are_identical(pp->type(), (*pa)->type(),
				  Type::COMPARE_TAGS, NULL))
	    args->push_back(*pa);
	  else
	    {
	      Location loc = (*pa)->location();
	      Expression* arg = *pa;
	      if (!arg->is_multi_eval_safe())
		{
		  Temporary_statement *temp =
		    Statement::make_temporary(NULL, arg, loc);
		  inserter->insert(temp);
		  arg = Expression::make_temporary_reference(temp, loc);
		}
	      arg = Expression::convert_for_assignment(gogo, pp->type(), arg,
						       loc);
	      args->push_back(arg);
	    }
	}
      delete this->args_;
      this->args_ = args;
    }

  // Lower to compiler intrinsic if possible.
  Func_expression* fe = this->fn_->func_expression();
  if (!this->is_concurrent_ && !this->is_deferred_
      && fe != NULL
      && (fe->named_object()->is_function_declaration()
          || fe->named_object()->is_function()))
    {
      Expression* ret = this->intrinsify(gogo, inserter);
      if (ret != NULL)
        return ret;
    }

  // Add an implicit conversion to a boolean type, if needed.  See the
  // comment in Binary_expression::lower_array_comparison.
  if (this->is_equal_function_
      && this->type_ != NULL
      && this->type_ != Type::lookup_bool_type())
    return Expression::make_cast(this->type_, this, this->location());

  return this;
}

// Lower a call to a compiler intrinsic if possible.
// Returns NULL if it is not an intrinsic.

Expression*
Call_expression::intrinsify(Gogo* gogo,
                            Statement_inserter* inserter)
{
  Func_expression* fe = this->fn_->func_expression();
  Named_object* no = fe->named_object();
  std::string name = Gogo::unpack_hidden_name(no->name());
  std::string package = (no->package() != NULL
                         ? no->package()->pkgpath()
                         : gogo->pkgpath());
  Location loc = this->location();

  Type* int_type = Type::lookup_integer_type("int");
  Type* int32_type = Type::lookup_integer_type("int32");
  Type* int64_type = Type::lookup_integer_type("int64");
  Type* uint_type = Type::lookup_integer_type("uint");
  Type* uint32_type = Type::lookup_integer_type("uint32");
  Type* uint64_type = Type::lookup_integer_type("uint64");
  Type* uintptr_type = Type::lookup_integer_type("uintptr");
  Type* pointer_type = Type::make_pointer_type(Type::make_void_type());

  int int_size = int_type->named_type()->real_type()->integer_type()->bits() / 8;
  int ptr_size = uintptr_type->named_type()->real_type()->integer_type()->bits() / 8;

  if (package == "sync/atomic")
    {
      // sync/atomic functions and runtime/internal/atomic functions
      // are very similar. In order not to duplicate code, we just
      // redirect to the latter and let the code below to handle them.
      // In case there is no equivalent functions (slight variance
      // in types), we just make an artificial name (begin with '$').
      // Note: no StorePointer, SwapPointer, and CompareAndSwapPointer,
      // as they need write barriers.
      if (name == "LoadInt32")
        name = "$Loadint32";
      else if (name == "LoadInt64")
        name = "Loadint64";
      else if (name == "LoadUint32")
        name = "Load";
      else if (name == "LoadUint64")
        name = "Load64";
      else if (name == "LoadUintptr")
        name = "Loaduintptr";
      else if (name == "LoadPointer")
        name = "Loadp";
      else if (name == "StoreInt32")
        name = "$Storeint32";
      else if (name == "StoreInt64")
        name = "$Storeint64";
      else if (name == "StoreUint32")
        name = "Store";
      else if (name == "StoreUint64")
        name = "Store64";
      else if (name == "StoreUintptr")
        name = "Storeuintptr";
      else if (name == "AddInt32")
        name = "$Xaddint32";
      else if (name == "AddInt64")
        name = "Xaddint64";
      else if (name == "AddUint32")
        name = "Xadd";
      else if (name == "AddUint64")
        name = "Xadd64";
      else if (name == "AddUintptr")
        name = "Xadduintptr";
      else if (name == "SwapInt32")
        name = "$Xchgint32";
      else if (name == "SwapInt64")
        name = "$Xchgint64";
      else if (name == "SwapUint32")
        name = "Xchg";
      else if (name == "SwapUint64")
        name = "Xchg64";
      else if (name == "SwapUintptr")
        name = "Xchguintptr";
      else if (name == "CompareAndSwapInt32")
        name = "$Casint32";
      else if (name == "CompareAndSwapInt64")
        name = "$Casint64";
      else if (name == "CompareAndSwapUint32")
        name = "Cas";
      else if (name == "CompareAndSwapUint64")
        name = "Cas64";
      else if (name == "CompareAndSwapUintptr")
        name = "Casuintptr";
      else
        return NULL;

      package = "runtime/internal/atomic";
    }

  if (package == "runtime/internal/sys")
    {
      // runtime/internal/sys functions and math/bits functions
      // are very similar. In order not to duplicate code, we just
      // redirect to the latter and let the code below to handle them.
      if (name == "Bswap32")
        name = "ReverseBytes32";
      else if (name == "Bswap64")
        name = "ReverseBytes64";
      else if (name == "Ctz32")
        name = "TrailingZeros32";
      else if (name == "Ctz64")
        name = "TrailingZeros64";
      else
        return NULL;

      package = "math/bits";
    }

  if (package == "runtime")
    {
      // Handle a couple of special runtime functions.  In the runtime
      // package, getcallerpc returns the PC of the caller, and
      // getcallersp returns the frame pointer of the caller.  Implement
      // these by turning them into calls to GCC builtin functions.  We
      // could implement them in normal code, but then we would have to
      // explicitly unwind the stack.  These functions are intended to be
      // efficient.  Note that this technique obviously only works for
      // direct calls, but that is the only way they are used.
      if (name == "getcallerpc"
          && (this->args_ == NULL || this->args_->size() == 0))
        {
          Expression* arg = Expression::make_integer_ul(0, uint32_type, loc);
          Expression* call =
            Runtime::make_call(Runtime::BUILTIN_RETURN_ADDRESS, loc,
                               1, arg);
          // The builtin functions return void*, but the Go functions return uintptr.
          return Expression::make_cast(uintptr_type, call, loc);
        }
      else if (name == "getcallersp"
               && (this->args_ == NULL || this->args_->size() == 0))

        {
          Expression* call =
            Runtime::make_call(Runtime::BUILTIN_DWARF_CFA, loc, 0);
          // The builtin functions return void*, but the Go functions return uintptr.
          return Expression::make_cast(uintptr_type, call, loc);
        }
    }
  else if (package == "math/bits")
    {
      if ((name == "ReverseBytes16" || name == "ReverseBytes32"
           || name == "ReverseBytes64" || name == "ReverseBytes")
          && this->args_ != NULL && this->args_->size() == 1)
        {
          Runtime::Function code;
          if (name == "ReverseBytes16")
            code = Runtime::BUILTIN_BSWAP16;
          else if (name == "ReverseBytes32")
            code = Runtime::BUILTIN_BSWAP32;
          else if (name == "ReverseBytes64")
            code = Runtime::BUILTIN_BSWAP64;
          else if (name == "ReverseBytes")
            code = (int_size == 8 ? Runtime::BUILTIN_BSWAP64 : Runtime::BUILTIN_BSWAP32);
          else
            go_unreachable();
          Expression* arg = this->args_->front();
          Expression* call = Runtime::make_call(code, loc, 1, arg);
          if (name == "ReverseBytes")
            return Expression::make_cast(uint_type, call, loc);
          return call;
        }
      else if ((name == "TrailingZeros8" || name == "TrailingZeros16")
               && this->args_ != NULL && this->args_->size() == 1)
        {
          // GCC does not have a ctz8 or ctz16 intrinsic. We do
          // ctz32(0x100 | arg) or ctz32(0x10000 | arg).
          Expression* arg = this->args_->front();
          arg = Expression::make_cast(uint32_type, arg, loc);
          unsigned long mask = (name == "TrailingZeros8" ? 0x100 : 0x10000);
          Expression* c = Expression::make_integer_ul(mask, uint32_type, loc);
          arg = Expression::make_binary(OPERATOR_OR, arg, c, loc);
          Expression* call = Runtime::make_call(Runtime::BUILTIN_CTZ, loc, 1, arg);
          return Expression::make_cast(int_type, call, loc);
        }
      else if ((name == "TrailingZeros32"
                || (name == "TrailingZeros" && int_size == 4))
               && this->args_ != NULL && this->args_->size() == 1)
        {
          Expression* arg = this->args_->front();
          if (!arg->is_multi_eval_safe())
            {
              Temporary_statement* ts = Statement::make_temporary(uint32_type, arg, loc);
              inserter->insert(ts);
              arg = Expression::make_temporary_reference(ts, loc);
            }
          // arg == 0 ? 32 : __builtin_ctz(arg)
          Expression* zero = Expression::make_integer_ul(0, uint32_type, loc);
          Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
          Expression* c32 = Expression::make_integer_ul(32, int_type, loc);
          Expression* call = Runtime::make_call(Runtime::BUILTIN_CTZ, loc, 1, arg->copy());
          call = Expression::make_cast(int_type, call, loc);
          return Expression::make_conditional(cmp, c32, call, loc);
        }
      else if ((name == "TrailingZeros64"
                || (name == "TrailingZeros" && int_size == 8))
               && this->args_ != NULL && this->args_->size() == 1)
        {
          Expression* arg = this->args_->front();
          if (!arg->is_multi_eval_safe())
            {
              Temporary_statement* ts = Statement::make_temporary(uint64_type, arg, loc);
              inserter->insert(ts);
              arg = Expression::make_temporary_reference(ts, loc);
            }
          // arg == 0 ? 64 : __builtin_ctzll(arg)
          Expression* zero = Expression::make_integer_ul(0, uint64_type, loc);
          Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
          Expression* c64 = Expression::make_integer_ul(64, int_type, loc);
          Expression* call = Runtime::make_call(Runtime::BUILTIN_CTZLL, loc, 1, arg->copy());
          call = Expression::make_cast(int_type, call, loc);
          return Expression::make_conditional(cmp, c64, call, loc);
        }
      else if ((name == "LeadingZeros8" || name == "LeadingZeros16"
                || name == "Len8" || name == "Len16")
               && this->args_ != NULL && this->args_->size() == 1)
        {
          // GCC does not have a clz8 ir clz16 intrinsic. We do
          // clz32(arg<<24 | 0xffffff) or clz32(arg<<16 | 0xffff).
          Expression* arg = this->args_->front();
          arg = Expression::make_cast(uint32_type, arg, loc);
          unsigned long shift =
            ((name == "LeadingZeros8" || name == "Len8") ? 24 : 16);
          Expression* c = Expression::make_integer_ul(shift, uint32_type, loc);
          arg = Expression::make_binary(OPERATOR_LSHIFT, arg, c, loc);
          unsigned long mask =
            ((name == "LeadingZeros8" || name == "Len8") ? 0xffffff : 0xffff);
          c = Expression::make_integer_ul(mask, uint32_type, loc);
          arg = Expression::make_binary(OPERATOR_OR, arg, c, loc);
          Expression* call = Runtime::make_call(Runtime::BUILTIN_CLZ, loc, 1, arg);
          call = Expression::make_cast(int_type, call, loc);
          // len = width - clz
          if (name == "Len8")
            {
              c = Expression::make_integer_ul(8, int_type, loc);
              return Expression::make_binary(OPERATOR_MINUS, c, call, loc);
            }
          else if (name == "Len16")
            {
              c = Expression::make_integer_ul(16, int_type, loc);
              return Expression::make_binary(OPERATOR_MINUS, c, call, loc);
            }
          return call;
        }
      else if ((name == "LeadingZeros32" || name == "Len32"
                || ((name == "LeadingZeros" || name == "Len") && int_size == 4))
               && this->args_ != NULL && this->args_->size() == 1)
        {
          Expression* arg = this->args_->front();
          if (!arg->is_multi_eval_safe())
            {
              Temporary_statement* ts = Statement::make_temporary(uint32_type, arg, loc);
              inserter->insert(ts);
              arg = Expression::make_temporary_reference(ts, loc);
            }
          // arg == 0 ? 32 : __builtin_clz(arg)
          Expression* zero = Expression::make_integer_ul(0, uint32_type, loc);
          Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
          Expression* c32 = Expression::make_integer_ul(32, int_type, loc);
          Expression* call = Runtime::make_call(Runtime::BUILTIN_CLZ, loc, 1, arg->copy());
          call = Expression::make_cast(int_type, call, loc);
          Expression* cond = Expression::make_conditional(cmp, c32, call, loc);
          // len = 32 - clz
          if (name == "Len32" || name == "Len")
            return Expression::make_binary(OPERATOR_MINUS, c32->copy(), cond, loc);
          return cond;
        }
      else if ((name == "LeadingZeros64" || name == "Len64"
                || ((name == "LeadingZeros" || name == "Len") && int_size == 8))
               && this->args_ != NULL && this->args_->size() == 1)
        {
          Expression* arg = this->args_->front();
          if (!arg->is_multi_eval_safe())
            {
              Temporary_statement* ts = Statement::make_temporary(uint64_type, arg, loc);
              inserter->insert(ts);
              arg = Expression::make_temporary_reference(ts, loc);
            }
          // arg == 0 ? 64 : __builtin_clzll(arg)
          Expression* zero = Expression::make_integer_ul(0, uint64_type, loc);
          Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
          Expression* c64 = Expression::make_integer_ul(64, int_type, loc);
          Expression* call = Runtime::make_call(Runtime::BUILTIN_CLZLL, loc, 1, arg->copy());
          call = Expression::make_cast(int_type, call, loc);
          Expression* cond = Expression::make_conditional(cmp, c64, call, loc);
          // len = 64 - clz
          if (name == "Len64" || name == "Len")
            return Expression::make_binary(OPERATOR_MINUS, c64->copy(), cond, loc);
          return cond;
        }
      else if ((name == "OnesCount8" || name == "OnesCount16"
           || name == "OnesCount32" || name == "OnesCount64"
           || name == "OnesCount")
          && this->args_ != NULL && this->args_->size() == 1)
        {
          Runtime::Function code;
          if (name == "OnesCount64")
            code = Runtime::BUILTIN_POPCOUNTLL;
          else if (name == "OnesCount")
            code = (int_size == 8 ? Runtime::BUILTIN_POPCOUNTLL : Runtime::BUILTIN_POPCOUNT);
          else
            code = Runtime::BUILTIN_POPCOUNT;
          Expression* arg = this->args_->front();
          Expression* call = Runtime::make_call(code, loc, 1, arg);
          return Expression::make_cast(int_type, call, loc);
        }
    }
  else if (package == "runtime/internal/atomic")
    {
      int memorder = __ATOMIC_SEQ_CST;

      if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
           || name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
           || name == "$Loadint32")
          && this->args_ != NULL && this->args_->size() == 1)
        {
          if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
            // On 32-bit architectures we need to check alignment.
            // Not intrinsify for now.
            return NULL;

          Runtime::Function code;
          Type* res_type;
          if (name == "Load")
            {
              code = Runtime::ATOMIC_LOAD_4;
              res_type = uint32_type;
            }
          else if (name == "Load64")
            {
              code = Runtime::ATOMIC_LOAD_8;
              res_type = uint64_type;
            }
          else if (name == "$Loadint32")
            {
              code = Runtime::ATOMIC_LOAD_4;
              res_type = int32_type;
            }
          else if (name == "Loadint64")
            {
              code = Runtime::ATOMIC_LOAD_8;
              res_type = int64_type;
            }
          else if (name == "Loaduint")
            {
              code = (int_size == 8
                      ? Runtime::ATOMIC_LOAD_8
                      : Runtime::ATOMIC_LOAD_4);
              res_type = uint_type;
            }
          else if (name == "Loaduintptr")
            {
              code = (ptr_size == 8
                      ? Runtime::ATOMIC_LOAD_8
                      : Runtime::ATOMIC_LOAD_4);
              res_type = uintptr_type;
            }
          else if (name == "Loadp")
            {
              code = (ptr_size == 8
                      ? Runtime::ATOMIC_LOAD_8
                      : Runtime::ATOMIC_LOAD_4);
              res_type = pointer_type;
            }
          else if (name == "LoadAcq")
            {
              code = Runtime::ATOMIC_LOAD_4;
              res_type = uint32_type;
              memorder = __ATOMIC_ACQUIRE;
            }
          else
            go_unreachable();
          Expression* a1 = this->args_->front();
          Expression* a2 = Expression::make_integer_ul(memorder, int32_type, loc);
          Expression* call = Runtime::make_call(code, loc, 2, a1, a2);
          return Expression::make_unsafe_cast(res_type, call, loc);
        }

      if ((name == "Store" || name == "Store64" || name == "StorepNoWB"
           || name == "Storeuintptr" || name == "StoreRel"
           || name == "$Storeint32" || name == "$Storeint64")
          && this->args_ != NULL && this->args_->size() == 2)
        {
          if (int_size < 8 && (name == "Store64" || name == "$Storeint64"))
            return NULL;

          Runtime::Function code;
          Expression* a1 = this->args_->at(0);
          Expression* a2 = this->args_->at(1);
          if (name == "Store")
            code = Runtime::ATOMIC_STORE_4;
          else if (name == "Store64")
            code = Runtime::ATOMIC_STORE_8;
          else if (name == "$Storeint32")
            code = Runtime::ATOMIC_STORE_4;
          else if (name == "$Storeint64")
            code = Runtime::ATOMIC_STORE_8;
          else if (name == "Storeuintptr")
            code = (ptr_size == 8 ? Runtime::ATOMIC_STORE_8 : Runtime::ATOMIC_STORE_4);
          else if (name == "StorepNoWB")
            {
              code = (ptr_size == 8 ? Runtime::ATOMIC_STORE_8 : Runtime::ATOMIC_STORE_4);
              a2 = Expression::make_unsafe_cast(uintptr_type, a2, loc);
              a2 = Expression::make_cast(uint64_type, a2, loc);
            }
          else if (name == "StoreRel")
            {
              code = Runtime::ATOMIC_STORE_4;
              memorder = __ATOMIC_RELEASE;
            }
          else
            go_unreachable();
          Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
          return Runtime::make_call(code, loc, 3, a1, a2, a3);
        }

      if ((name == "Xchg" || name == "Xchg64" || name == "Xchguintptr"
           || name == "$Xchgint32" || name == "$Xchgint64")
          && this->args_ != NULL && this->args_->size() == 2)
        {
          if (int_size < 8 && (name == "Xchg64" || name == "Xchgint64"))
            return NULL;

          Runtime::Function code;
          Type* res_type;
          if (name == "Xchg")
            {
              code = Runtime::ATOMIC_EXCHANGE_4;
              res_type = uint32_type;
            }
          else if (name == "Xchg64")
            {
              code = Runtime::ATOMIC_EXCHANGE_8;
              res_type = uint64_type;
            }
          else if (name == "$Xchgint32")
            {
              code = Runtime::ATOMIC_EXCHANGE_4;
              res_type = int32_type;
            }
          else if (name == "$Xchgint64")
            {
              code = Runtime::ATOMIC_EXCHANGE_8;
              res_type = int64_type;
            }
          else if (name == "Xchguintptr")
            {
              code = (ptr_size == 8
                      ? Runtime::ATOMIC_EXCHANGE_8
                      : Runtime::ATOMIC_EXCHANGE_4);
              res_type = uintptr_type;
            }
          else
            go_unreachable();
          Expression* a1 = this->args_->at(0);
          Expression* a2 = this->args_->at(1);
          Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
          Expression* call = Runtime::make_call(code, loc, 3, a1, a2, a3);
          return Expression::make_cast(res_type, call, loc);
        }

      if ((name == "Cas" || name == "Cas64" || name == "Casuintptr"
           || name == "Casp1" || name == "CasRel"
           || name == "$Casint32" || name == "$Casint64")
          && this->args_ != NULL && this->args_->size() == 3)
        {
          if (int_size < 8 && (name == "Cas64" || name == "$Casint64"))
            return NULL;

          Runtime::Function code;
          Expression* a1 = this->args_->at(0);

          // Builtin cas takes a pointer to the old value.
          // Store it in a temporary and take the address.
          Expression* a2 = this->args_->at(1);
          Temporary_statement* ts = Statement::make_temporary(NULL, a2, loc);
          inserter->insert(ts);
          a2 = Expression::make_temporary_reference(ts, loc);
          a2 = Expression::make_unary(OPERATOR_AND, a2, loc);

          Expression* a3 = this->args_->at(2);
          if (name == "Cas")
            code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
          else if (name == "Cas64")
            code = Runtime::ATOMIC_COMPARE_EXCHANGE_8;
          else if (name == "$Casint32")
            code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
          else if (name == "$Casint64")
            code = Runtime::ATOMIC_COMPARE_EXCHANGE_8;
          else if (name == "Casuintptr")
            code = (ptr_size == 8
                    ? Runtime::ATOMIC_COMPARE_EXCHANGE_8
                    : Runtime::ATOMIC_COMPARE_EXCHANGE_4);
          else if (name == "Casp1")
            {
              code = (ptr_size == 8
                      ? Runtime::ATOMIC_COMPARE_EXCHANGE_8
                      : Runtime::ATOMIC_COMPARE_EXCHANGE_4);
              a3 = Expression::make_unsafe_cast(uintptr_type, a3, loc);
              a3 = Expression::make_cast(uint64_type, a3, loc);
            }
          else if (name == "CasRel")
            {
              code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
              memorder = __ATOMIC_RELEASE;
            }
          else
            go_unreachable();
          Expression* a4 = Expression::make_boolean(false, loc);
          Expression* a5 = Expression::make_integer_ul(memorder, int32_type, loc);
          Expression* a6 = Expression::make_integer_ul(__ATOMIC_RELAXED, int32_type, loc);
          return Runtime::make_call(code, loc, 6, a1, a2, a3, a4, a5, a6);
        }

      if ((name == "Xadd" || name == "Xadd64" || name == "Xaddint64"
           || name == "Xadduintptr" || name == "$Xaddint32")
          && this->args_ != NULL && this->args_->size() == 2)
        {
          if (int_size < 8 && (name == "Xadd64" || name == "Xaddint64"))
            return NULL;

          Runtime::Function code;
          Type* res_type;
          if (name == "Xadd")
            {
              code = Runtime::ATOMIC_ADD_FETCH_4;
              res_type = uint32_type;
            }
          else if (name == "Xadd64")
            {
              code = Runtime::ATOMIC_ADD_FETCH_8;
              res_type = uint64_type;
            }
          else if (name == "$Xaddint32")
            {
              code = Runtime::ATOMIC_ADD_FETCH_4;
              res_type = int32_type;
            }
          else if (name == "Xaddint64")
            {
              code = Runtime::ATOMIC_ADD_FETCH_8;
              res_type = int64_type;
            }
          else if (name == "Xadduintptr")
            {
              code = (ptr_size == 8
                      ? Runtime::ATOMIC_ADD_FETCH_8
                      : Runtime::ATOMIC_ADD_FETCH_4);
              res_type = uintptr_type;
            }
          else
            go_unreachable();
          Expression* a1 = this->args_->at(0);
          Expression* a2 = this->args_->at(1);
          Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
          Expression* call = Runtime::make_call(code, loc, 3, a1, a2, a3);
          return Expression::make_cast(res_type, call, loc);
        }

      if ((name == "And8" || name == "Or8")
          && this->args_ != NULL && this->args_->size() == 2)
        {
          Runtime::Function code;
          if (name == "And8")
            code = Runtime::ATOMIC_AND_FETCH_1;
          else if (name == "Or8")
            code = Runtime::ATOMIC_OR_FETCH_1;
          else
            go_unreachable();
          Expression* a1 = this->args_->at(0);
          Expression* a2 = this->args_->at(1);
          Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
          return Runtime::make_call(code, loc, 3, a1, a2, a3);
        }
    }

  return NULL;
}

// Make implicit type conversions explicit.

void
Call_expression::do_add_conversions()
{
  // Skip call that requires a thunk. We generate conversions inside the thunk.
  if (this->is_concurrent_ || this->is_deferred_)
    return;

  if (this->args_ == NULL || this->args_->empty())
    return;

  Function_type* fntype = this->get_function_type();
  if (fntype == NULL)
    {
      go_assert(saw_errors());
      return;
    }
  if (fntype->parameters() == NULL || fntype->parameters()->empty())
    return;

  Location loc = this->location();
  Expression_list::iterator pa = this->args_->begin();
  Typed_identifier_list::const_iterator pp = fntype->parameters()->begin();
  bool is_interface_method =
    this->fn_->interface_field_reference_expression() != NULL;
  size_t argcount = this->args_->size();
  if (!is_interface_method && fntype->is_method())
    {
      // Skip the receiver argument, which cannot be interface.
      pa++;
      argcount--;
    }
  if (argcount != fntype->parameters()->size())
    {
      go_assert(saw_errors());
      return;
    }
  for (; pa != this->args_->end(); ++pa, ++pp)
    {
      Type* pt = pp->type();
      if (!Type::are_identical(pt, (*pa)->type(), 0, NULL)
          && pt->interface_type() != NULL)
        *pa = Expression::make_cast(pt, *pa, loc);
    }
}

// Get the function type.  This can return NULL in error cases.

Function_type*
Call_expression::get_function_type() const
{
  return this->fn_->type()->function_type();
}

// Return the number of values which this call will return.

size_t
Call_expression::result_count() const
{
  const Function_type* fntype = this->get_function_type();
  if (fntype == NULL)
    return 0;
  if (fntype->results() == NULL)
    return 0;
  return fntype->results()->size();
}

// Return the temporary that holds the result for a call with multiple
// results.

Temporary_statement*
Call_expression::results() const
{
  if (this->call_temp_ == NULL)
    {
      go_assert(saw_errors());
      return NULL;
    }
  return this->call_temp_;
}

// Set the number of results expected from a call expression.

void
Call_expression::set_expected_result_count(size_t count)
{
  go_assert(this->expected_result_count_ == 0);
  this->expected_result_count_ = count;
}

// Return whether this is a call to the predeclared function recover.

bool
Call_expression::is_recover_call() const
{
  return this->do_is_recover_call();
}

// Set the argument to the recover function.

void
Call_expression::set_recover_arg(Expression* arg)
{
  this->do_set_recover_arg(arg);
}

// Virtual functions also implemented by Builtin_call_expression.

bool
Call_expression::do_is_recover_call() const
{
  return false;
}

void
Call_expression::do_set_recover_arg(Expression*)
{
  go_unreachable();
}

// We have found an error with this call expression; return true if
// we should report it.

bool
Call_expression::issue_error()
{
  if (this->issued_error_)
    return false;
  else
    {
      this->issued_error_ = true;
      return true;
    }
}

// Whether or not this call contains errors, either in the call or the
// arguments to the call.

bool
Call_expression::is_erroneous_call()
{
  if (this->is_error_expression() || this->fn()->is_error_expression())
    return true;

  if (this->args() == NULL)
    return false;
  for (Expression_list::iterator pa = this->args()->begin();
       pa != this->args()->end();
       ++pa)
    {
      if ((*pa)->type()->is_error_type() || (*pa)->is_error_expression())
        return true;
    }
  return false;
}

// Get the type.

Type*
Call_expression::do_type()
{
  if (this->is_error_expression())
    return Type::make_error_type();
  if (this->type_ != NULL)
    return this->type_;

  Type* ret;
  Function_type* fntype = this->get_function_type();
  if (fntype == NULL)
    return Type::make_error_type();

  const Typed_identifier_list* results = fntype->results();
  if (results == NULL)
    ret = Type::make_void_type();
  else if (results->size() == 1)
    ret = results->begin()->type();
  else
    ret = Type::make_call_multiple_result_type(this);

  this->type_ = ret;

  return this->type_;
}

// Determine types for a call expression.  We can use the function
// parameter types to set the types of the arguments.

void
Call_expression::do_determine_type(const Type_context* context)
{
  if (!this->determining_types())
    return;

  this->fn_->determine_type_no_context();
  Function_type* fntype = this->get_function_type();
  const Typed_identifier_list* parameters = NULL;
  if (fntype != NULL)
    parameters = fntype->parameters();
  if (this->args_ != NULL)
    {
      Typed_identifier_list::const_iterator pt;
      if (parameters != NULL)
	pt = parameters->begin();
      bool first = true;
      for (Expression_list::const_iterator pa = this->args_->begin();
	   pa != this->args_->end();
	   ++pa)
	{
	  if (first)
	    {
	      first = false;
	      // If this is a method, the first argument is the
	      // receiver.
	      if (fntype != NULL && fntype->is_method())
		{
		  Type* rtype = fntype->receiver()->type();
		  // The receiver is always passed as a pointer.
		  if (rtype->points_to() == NULL)
		    rtype = Type::make_pointer_type(rtype);
		  Type_context subcontext(rtype, false);
		  (*pa)->determine_type(&subcontext);
		  continue;
		}
	    }

	  if (parameters != NULL && pt != parameters->end())
	    {
	      Type_context subcontext(pt->type(), false);
	      (*pa)->determine_type(&subcontext);
	      ++pt;
	    }
	  else
	    (*pa)->determine_type_no_context();
	}
    }

  // If this is a call to a generated equality function, we determine
  // the type based on the context.  See the comment in
  // Binary_expression::lower_array_comparison.
  if (this->is_equal_function_
      && !context->may_be_abstract
      && context->type != NULL
      && context->type->is_boolean_type()
      && context->type != Type::lookup_bool_type())
    {
      go_assert(this->type_ == NULL
		|| this->type_ == Type::lookup_bool_type()
		|| this->type_ == context->type
		|| this->type_->is_error());
      this->type_ = context->type;
    }
}

// Called when determining types for a Call_expression.  Return true
// if we should go ahead, false if they have already been determined.

bool
Call_expression::determining_types()
{
  if (this->types_are_determined_)
    return false;
  else
    {
      this->types_are_determined_ = true;
      return true;
    }
}

// Check types for parameter I.

bool
Call_expression::check_argument_type(int i, const Type* parameter_type,
				     const Type* argument_type,
				     Location argument_location,
				     bool issued_error)
{
  std::string reason;
  if (!Type::are_assignable(parameter_type, argument_type, &reason))
    {
      if (!issued_error)
	{
	  if (reason.empty())
	    go_error_at(argument_location, "argument %d has incompatible type", i);
	  else
	    go_error_at(argument_location,
			"argument %d has incompatible type (%s)",
			i, reason.c_str());
	}
      this->set_is_error();
      return false;
    }
  return true;
}

// Check types.

void
Call_expression::do_check_types(Gogo*)
{
  if (this->classification() == EXPRESSION_ERROR)
    return;

  Function_type* fntype = this->get_function_type();
  if (fntype == NULL)
    {
      if (!this->fn_->type()->is_error())
	this->report_error(_("expected function"));
      return;
    }

  if (this->expected_result_count_ != 0
      && this->expected_result_count_ != this->result_count())
    {
      if (this->issue_error())
	this->report_error(_("function result count mismatch"));
      this->set_is_error();
      return;
    }

  bool is_method = fntype->is_method();
  if (is_method)
    {
      go_assert(this->args_ != NULL && !this->args_->empty());
      Type* rtype = fntype->receiver()->type();
      Expression* first_arg = this->args_->front();
      // We dereference the values since receivers are always passed
      // as pointers.
      std::string reason;
      if (!Type::are_assignable(rtype->deref(), first_arg->type()->deref(),
				&reason))
	{
	  if (reason.empty())
	    this->report_error(_("incompatible type for receiver"));
	  else
	    {
	      go_error_at(this->location(),
                          "incompatible type for receiver (%s)",
                          reason.c_str());
	      this->set_is_error();
	    }
	}
    }

  // Note that varargs was handled by the lower_varargs() method, so
  // we don't have to worry about it here unless something is wrong.
  if (this->is_varargs_ && !this->varargs_are_lowered_)
    {
      if (!fntype->is_varargs())
	{
	  go_error_at(this->location(),
                      _("invalid use of %<...%> calling non-variadic function"));
	  this->set_is_error();
	  return;
	}
    }

  const Typed_identifier_list* parameters = fntype->parameters();
  if (this->args_ == NULL || this->args_->size() == 0)
    {
      if (parameters != NULL && !parameters->empty())
	this->report_error(_("not enough arguments"));
    }
  else if (parameters == NULL)
    {
      if (!is_method || this->args_->size() > 1)
	this->report_error(_("too many arguments"));
    }
  else if (this->args_->size() == 1
	   && this->args_->front()->call_expression() != NULL
	   && this->args_->front()->call_expression()->result_count() > 1)
    {
      // This is F(G()) when G returns more than one result.  If the
      // results can be matched to parameters, it would have been
      // lowered in do_lower.  If we get here we know there is a
      // mismatch.
      if (this->args_->front()->call_expression()->result_count()
	  < parameters->size())
	this->report_error(_("not enough arguments"));
      else
	this->report_error(_("too many arguments"));
    }
  else
    {
      int i = 0;
      Expression_list::const_iterator pa = this->args_->begin();
      if (is_method)
	++pa;
      for (Typed_identifier_list::const_iterator pt = parameters->begin();
	   pt != parameters->end();
	   ++pt, ++pa, ++i)
	{
	  if (pa == this->args_->end())
	    {
	      this->report_error(_("not enough arguments"));
	      return;
	    }
	  this->check_argument_type(i + 1, pt->type(), (*pa)->type(),
				    (*pa)->location(), false);
	}
      if (pa != this->args_->end())
	this->report_error(_("too many arguments"));
    }
}

Expression*
Call_expression::do_copy()
{
  Call_expression* call =
    Expression::make_call(this->fn_->copy(),
			  (this->args_ == NULL
			   ? NULL
			   : this->args_->copy()),
			  this->is_varargs_, this->location());

  if (this->varargs_are_lowered_)
    call->set_varargs_are_lowered();
  if (this->is_deferred_)
    call->set_is_deferred();
  if (this->is_concurrent_)
    call->set_is_concurrent();
  return call;
}

// Return whether we have to use a temporary variable to ensure that
// we evaluate this call expression in order.  If the call returns no
// results then it will inevitably be executed last.

bool
Call_expression::do_must_eval_in_order() const
{
  return this->result_count() > 0;
}

// Get the function and the first argument to use when calling an
// interface method.

Expression*
Call_expression::interface_method_function(
    Interface_field_reference_expression* interface_method,
    Expression** first_arg_ptr,
    Location location)
{
  Expression* object = interface_method->get_underlying_object();
  Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
  *first_arg_ptr =
      Expression::make_unsafe_cast(unsafe_ptr_type, object, location);
  return interface_method->get_function();
}

// Build the call expression.

Bexpression*
Call_expression::do_get_backend(Translate_context* context)
{
  Location location = this->location();

  if (this->call_ != NULL)
    {
      // If the call returns multiple results, make a new reference to
      // the temporary.
      if (this->call_temp_ != NULL)
	{
	  Expression* ref =
	    Expression::make_temporary_reference(this->call_temp_, location);
	  return ref->get_backend(context);
	}

      return this->call_;
    }

  Function_type* fntype = this->get_function_type();
  if (fntype == NULL)
    return context->backend()->error_expression();

  if (this->fn_->is_error_expression())
    return context->backend()->error_expression();

  Gogo* gogo = context->gogo();

  Func_expression* func = this->fn_->func_expression();
  Interface_field_reference_expression* interface_method =
    this->fn_->interface_field_reference_expression();
  const bool has_closure = func != NULL && func->closure() != NULL;
  const bool is_interface_method = interface_method != NULL;

  bool has_closure_arg;
  if (has_closure)
    has_closure_arg = true;
  else if (func != NULL)
    has_closure_arg = false;
  else if (is_interface_method)
    has_closure_arg = false;
  else
    has_closure_arg = true;

  Expression* first_arg = NULL;
  if (!is_interface_method && fntype->is_method())
    {
      first_arg = this->args_->front();
      if (first_arg->type()->points_to() == NULL
          && first_arg->type()->is_direct_iface_type())
        first_arg = Expression::unpack_direct_iface(first_arg,
                                                    first_arg->location());
    }

  int nargs;
  std::vector<Bexpression*> fn_args;
  if (this->args_ == NULL || this->args_->empty())
    {
      nargs = is_interface_method ? 1 : 0;
      if (nargs > 0)
        fn_args.resize(1);
    }
  else if (fntype->parameters() == NULL || fntype->parameters()->empty())
    {
      // Passing a receiver parameter.
      go_assert(!is_interface_method
		&& fntype->is_method()
		&& this->args_->size() == 1);
      nargs = 1;
      fn_args.resize(1);
      fn_args[0] = first_arg->get_backend(context);
    }
  else
    {
      const Typed_identifier_list* params = fntype->parameters();

      nargs = this->args_->size();
      int i = is_interface_method ? 1 : 0;
      nargs += i;
      fn_args.resize(nargs);

      Typed_identifier_list::const_iterator pp = params->begin();
      Expression_list::const_iterator pe = this->args_->begin();
      if (!is_interface_method && fntype->is_method())
	{
          fn_args[i] = first_arg->get_backend(context);
	  ++pe;
	  ++i;
	}
      for (; pe != this->args_->end(); ++pe, ++pp, ++i)
	{
	  go_assert(pp != params->end());
          Expression* arg =
              Expression::convert_for_assignment(gogo, pp->type(), *pe,
                                                 location);
          fn_args[i] = arg->get_backend(context);
	}
      go_assert(pp == params->end());
      go_assert(i == nargs);
    }

  Expression* fn;
  Expression* closure = NULL;
  if (func != NULL)
    {
      Named_object* no = func->named_object();
      fn = Expression::make_func_code_reference(no, location);
      if (has_closure)
        closure = func->closure();
    }
  else if (!is_interface_method)
    {
      closure = this->fn_;

      // The backend representation of this function type is a pointer
      // to a struct whose first field is the actual function to call.
      Type* pfntype =
          Type::make_pointer_type(
              Type::make_pointer_type(Type::make_void_type()));
      fn = Expression::make_unsafe_cast(pfntype, this->fn_, location);
      fn = Expression::make_dereference(fn, NIL_CHECK_NOT_NEEDED, location);
    }
  else
    {
      Expression* arg0;
      fn = this->interface_method_function(interface_method, &arg0,
                                           location);
      fn_args[0] = arg0->get_backend(context);
    }

  Bexpression* bclosure = NULL;
  if (has_closure_arg)
    bclosure = closure->get_backend(context);
  else
    go_assert(closure == NULL);

  Bexpression* bfn = fn->get_backend(context);

  // When not calling a named function directly, use a type conversion
  // in case the type of the function is a recursive type which refers
  // to itself.  We don't do this for an interface method because 1)
  // an interface method never refers to itself, so we always have a
  // function type here; 2) we pass an extra first argument to an
  // interface method, so fntype is not correct.
  if (func == NULL && !is_interface_method)
    {
      Btype* bft = fntype->get_backend_fntype(gogo);
      bfn = gogo->backend()->convert_expression(bft, bfn, location);
    }

  Bfunction* bfunction = NULL;
  if (context->function())
    bfunction = context->function()->func_value()->get_decl();
  Bexpression* call = gogo->backend()->call_expression(bfunction, bfn,
                                                       fn_args, bclosure,
                                                       location);

  if (this->call_temp_ != NULL)
    {
      // This case occurs when the call returns multiple results.

      Expression* ref = Expression::make_temporary_reference(this->call_temp_,
							     location);
      Bexpression* bref = ref->get_backend(context);
      Bstatement* bassn = gogo->backend()->assignment_statement(bfunction,
								bref, call,
								location);

      ref = Expression::make_temporary_reference(this->call_temp_, location);
      this->call_ = ref->get_backend(context);

      return gogo->backend()->compound_expression(bassn, this->call_,
						  location);
    }

  this->call_ = call;
  return this->call_;
}

// The cost of inlining a call expression.

int
Call_expression::do_inlining_cost() const
{
  Func_expression* fn = this->fn_->func_expression();

  // FIXME: We don't yet support all kinds of calls.
  if (fn != NULL && fn->closure() != NULL)
    return 0x100000;
  if (this->fn_->interface_field_reference_expression())
    return 0x100000;
  if (this->get_function_type()->is_method())
    return 0x100000;

  return 5;
}

// Export a call expression.

void
Call_expression::do_export(Export_function_body* efb) const
{
  bool simple_call = (this->fn_->func_expression() != NULL);
  if (!simple_call)
    efb->write_c_string("(");
  this->fn_->export_expression(efb);
  if (!simple_call)
    efb->write_c_string(")");
  this->export_arguments(efb);
}

// Export call expression arguments.

void
Call_expression::export_arguments(Export_function_body* efb) const
{
  efb->write_c_string("(");
  if (this->args_ != NULL && !this->args_->empty())
    {
      Expression_list::const_iterator pa = this->args_->begin();
      (*pa)->export_expression(efb);
      for (pa++; pa != this->args_->end(); pa++)
	{
	  efb->write_c_string(", ");
	  (*pa)->export_expression(efb);
	}
      if (this->is_varargs_)
	efb->write_c_string("...");
    }
  efb->write_c_string(")");
}

// Dump ast representation for a call expression.

void
Call_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  this->fn_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << "(";
  if (args_ != NULL)
    ast_dump_context->dump_expression_list(this->args_);

  ast_dump_context->ostream() << ") ";
}

// Make a call expression.

Call_expression*
Expression::make_call(Expression* fn, Expression_list* args, bool is_varargs,
		      Location location)
{
  return new Call_expression(fn, args, is_varargs, location);
}

// Class Call_result_expression.

// Traverse a call result.

int
Call_result_expression::do_traverse(Traverse* traverse)
{
  if (traverse->remember_expression(this->call_))
    {
      // We have already traversed the call expression.
      return TRAVERSE_CONTINUE;
    }
  return Expression::traverse(&this->call_, traverse);
}

// Get the type.

Type*
Call_result_expression::do_type()
{
  if (this->classification() == EXPRESSION_ERROR)
    return Type::make_error_type();

  // THIS->CALL_ can be replaced with a temporary reference due to
  // Call_expression::do_must_eval_in_order when there is an error.
  Call_expression* ce = this->call_->call_expression();
  if (ce == NULL)
    {
      this->set_is_error();
      return Type::make_error_type();
    }
  Function_type* fntype = ce->get_function_type();
  if (fntype == NULL)
    {
      if (ce->issue_error())
	{
	  if (!ce->fn()->type()->is_error())
	    this->report_error(_("expected function"));
	}
      this->set_is_error();
      return Type::make_error_type();
    }
  const Typed_identifier_list* results = fntype->results();
  if (results == NULL || results->size() < 2)
    {
      if (ce->issue_error())
	this->report_error(_("number of results does not match "
			     "number of values"));
      return Type::make_error_type();
    }
  Typed_identifier_list::const_iterator pr = results->begin();
  for (unsigned int i = 0; i < this->index_; ++i)
    {
      if (pr == results->end())
	break;
      ++pr;
    }
  if (pr == results->end())
    {
      if (ce->issue_error())
	this->report_error(_("number of results does not match "
			     "number of values"));
      return Type::make_error_type();
    }
  return pr->type();
}

// Check the type.  Just make sure that we trigger the warning in
// do_type.

void
Call_result_expression::do_check_types(Gogo*)
{
  this->type();
}

// Determine the type.  We have nothing to do here, but the 0 result
// needs to pass down to the caller.

void
Call_result_expression::do_determine_type(const Type_context*)
{
  this->call_->determine_type_no_context();
}

// Return the backend representation.  We just refer to the temporary set by the
// call expression.  We don't do this at lowering time because it makes it
// hard to evaluate the call at the right time.

Bexpression*
Call_result_expression::do_get_backend(Translate_context* context)
{
  Call_expression* ce = this->call_->call_expression();
  if (ce == NULL)
    {
      go_assert(this->call_->is_error_expression());
      return context->backend()->error_expression();
    }
  Temporary_statement* ts = ce->results();
  if (ts == NULL)
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }
  Expression* ref = Expression::make_temporary_reference(ts, this->location());
  ref = Expression::make_field_reference(ref, this->index_, this->location());
  return ref->get_backend(context);
}

// Dump ast representation for a call result expression.

void
Call_result_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  // FIXME: Wouldn't it be better if the call is assigned to a temporary
  // (struct) and the fields are referenced instead.
  ast_dump_context->ostream() << this->index_ << "@(";
  ast_dump_context->dump_expression(this->call_);
  ast_dump_context->ostream() << ")";
}

// Make a reference to a single result of a call which returns
// multiple results.

Expression*
Expression::make_call_result(Call_expression* call, unsigned int index)
{
  return new Call_result_expression(call, index);
}

// Class Index_expression.

// Traversal.

int
Index_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->left_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->start_, traverse) == TRAVERSE_EXIT
      || (this->end_ != NULL
	  && Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)
      || (this->cap_ != NULL
          && Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT))
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Lower an index expression.  This converts the generic index
// expression into an array index, a string index, or a map index.

Expression*
Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
{
  Location location = this->location();
  Expression* left = this->left_;
  Expression* start = this->start_;
  Expression* end = this->end_;
  Expression* cap = this->cap_;

  Type* type = left->type();
  if (type->is_error())
    {
      go_assert(saw_errors());
      return Expression::make_error(location);
    }
  else if (left->is_type_expression())
    {
      go_error_at(location, "attempt to index type expression");
      return Expression::make_error(location);
    }
  else if (type->array_type() != NULL)
    return Expression::make_array_index(left, start, end, cap, location);
  else if (type->points_to() != NULL
	   && type->points_to()->array_type() != NULL
	   && !type->points_to()->is_slice_type())
    {
      Expression* deref =
          Expression::make_dereference(left, NIL_CHECK_DEFAULT, location);

      // For an ordinary index into the array, the pointer will be
      // dereferenced.  For a slice it will not--the resulting slice
      // will simply reuse the pointer, which is incorrect if that
      // pointer is nil.
      if (end != NULL || cap != NULL)
	deref->issue_nil_check();

      return Expression::make_array_index(deref, start, end, cap, location);
    }
  else if (type->is_string_type())
    {
      if (cap != NULL)
        {
          go_error_at(location, "invalid 3-index slice of string");
          return Expression::make_error(location);
        }
      return Expression::make_string_index(left, start, end, location);
    }
  else if (type->map_type() != NULL)
    {
      if (end != NULL || cap != NULL)
	{
	  go_error_at(location, "invalid slice of map");
	  return Expression::make_error(location);
	}
      return Expression::make_map_index(left, start, location);
    }
  else if (cap != NULL)
    {
      go_error_at(location,
		  "invalid 3-index slice of object that is not a slice");
      return Expression::make_error(location);
    }
  else if (end != NULL)
    {
      go_error_at(location,
		  ("attempt to slice object that is not "
		   "array, slice, or string"));
      return Expression::make_error(location);
    }
  else
    {
      go_error_at(location,
                  ("attempt to index object that is not "
		   "array, slice, string, or map"));
      return Expression::make_error(location);
    }
}

// Write an indexed expression
// (expr[expr:expr:expr], expr[expr:expr] or expr[expr]) to a dump context.

void
Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context,
					const Expression* expr,
					const Expression* start,
					const Expression* end,
					const Expression* cap)
{
  expr->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << "[";
  start->dump_expression(ast_dump_context);
  if (end != NULL)
    {
      ast_dump_context->ostream() << ":";
      end->dump_expression(ast_dump_context);
    }
  if (cap != NULL)
    {
      ast_dump_context->ostream() << ":";
      cap->dump_expression(ast_dump_context);
    }
  ast_dump_context->ostream() << "]";
}

// Dump ast representation for an index expression.

void
Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  Index_expression::dump_index_expression(ast_dump_context, this->left_,
                                          this->start_, this->end_, this->cap_);
}

// Make an index expression.

Expression*
Expression::make_index(Expression* left, Expression* start, Expression* end,
		       Expression* cap, Location location)
{
  return new Index_expression(left, start, end, cap, location);
}

// Class Array_index_expression.

// Array index traversal.

int
Array_index_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->array_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (Expression::traverse(&this->start_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->end_ != NULL)
    {
      if (Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  if (this->cap_ != NULL)
    {
      if (Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT)
        return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Return the type of an array index.

Type*
Array_index_expression::do_type()
{
  if (this->type_ == NULL)
    {
     Array_type* type = this->array_->type()->array_type();
      if (type == NULL)
	this->type_ = Type::make_error_type();
      else if (this->end_ == NULL)
	this->type_ = type->element_type();
      else if (type->is_slice_type())
	{
	  // A slice of a slice has the same type as the original
	  // slice.
	  this->type_ = this->array_->type()->deref();
	}
      else
	{
	  // A slice of an array is a slice.
	  this->type_ = Type::make_array_type(type->element_type(), NULL);
	}
    }
  return this->type_;
}

// Set the type of an array index.

void
Array_index_expression::do_determine_type(const Type_context*)
{
  this->array_->determine_type_no_context();

  Type_context index_context(Type::lookup_integer_type("int"), false);
  this->start_->determine_type(&index_context);
  if (this->end_ != NULL)
    this->end_->determine_type(&index_context);
  if (this->cap_ != NULL)
    this->cap_->determine_type(&index_context);
}

// Check types of an array index.

void
Array_index_expression::do_check_types(Gogo*)
{
  Numeric_constant nc;
  unsigned long v;
  if (this->start_->type()->integer_type() == NULL
      && !this->start_->type()->is_error()
      && (!this->start_->type()->is_abstract()
	  || !this->start_->numeric_constant_value(&nc)
	  || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
    this->report_error(_("index must be integer"));
  if (this->end_ != NULL
      && this->end_->type()->integer_type() == NULL
      && !this->end_->type()->is_error()
      && !this->end_->is_nil_expression()
      && !this->end_->is_error_expression()
      && (!this->end_->type()->is_abstract()
	  || !this->end_->numeric_constant_value(&nc)
	  || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
    this->report_error(_("slice end must be integer"));
  if (this->cap_ != NULL
      && this->cap_->type()->integer_type() == NULL
      && !this->cap_->type()->is_error()
      && !this->cap_->is_nil_expression()
      && !this->cap_->is_error_expression()
      && (!this->cap_->type()->is_abstract()
	  || !this->cap_->numeric_constant_value(&nc)
	  || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
    this->report_error(_("slice capacity must be integer"));

  Array_type* array_type = this->array_->type()->array_type();
  if (array_type == NULL)
    {
      go_assert(this->array_->type()->is_error());
      return;
    }

  unsigned int int_bits =
    Type::lookup_integer_type("int")->integer_type()->bits();

  Numeric_constant lvalnc;
  mpz_t lval;
  bool lval_valid = (array_type->length() != NULL
		     && array_type->length()->numeric_constant_value(&lvalnc)
		     && lvalnc.to_int(&lval));
  Numeric_constant inc;
  mpz_t ival;
  bool ival_valid = false;
  if (this->start_->numeric_constant_value(&inc) && inc.to_int(&ival))
    {
      ival_valid = true;
      if (mpz_sgn(ival) < 0
	  || mpz_sizeinbase(ival, 2) >= int_bits
	  || (lval_valid
	      && (this->end_ == NULL
		  ? mpz_cmp(ival, lval) >= 0
		  : mpz_cmp(ival, lval) > 0)))
	{
	  go_error_at(this->start_->location(), "array index out of bounds");
	  this->set_is_error();
	}
    }
  if (this->end_ != NULL && !this->end_->is_nil_expression())
    {
      Numeric_constant enc;
      mpz_t eval;
      bool eval_valid = false;
      if (this->end_->numeric_constant_value(&enc) && enc.to_int(&eval))
	{
	  eval_valid = true;
	  if (mpz_sgn(eval) < 0
	      || mpz_sizeinbase(eval, 2) >= int_bits
	      || (lval_valid && mpz_cmp(eval, lval) > 0))
	    {
	      go_error_at(this->end_->location(), "array index out of bounds");
	      this->set_is_error();
	    }
	  else if (ival_valid && mpz_cmp(ival, eval) > 0)
	    this->report_error(_("inverted slice range"));
	}

      Numeric_constant cnc;
      mpz_t cval;
      if (this->cap_ != NULL
          && this->cap_->numeric_constant_value(&cnc) && cnc.to_int(&cval))
        {
          if (mpz_sgn(cval) < 0
              || mpz_sizeinbase(cval, 2) >= int_bits
              || (lval_valid && mpz_cmp(cval, lval) > 0))
            {
              go_error_at(this->cap_->location(), "array index out of bounds");
              this->set_is_error();
            }
	  else if (ival_valid && mpz_cmp(ival, cval) > 0)
	    {
	      go_error_at(this->cap_->location(),
                          "invalid slice index: capacity less than start");
	      this->set_is_error();
	    }
          else if (eval_valid && mpz_cmp(eval, cval) > 0)
            {
              go_error_at(this->cap_->location(),
                          "invalid slice index: capacity less than length");
              this->set_is_error();
            }
          mpz_clear(cval);
        }

      if (eval_valid)
        mpz_clear(eval);
    }
  if (ival_valid)
    mpz_clear(ival);
  if (lval_valid)
    mpz_clear(lval);

  // A slice of an array requires an addressable array.  A slice of a
  // slice is always possible.
  if (this->end_ != NULL && !array_type->is_slice_type())
    {
      if (!this->array_->is_addressable())
	this->report_error(_("slice of unaddressable value"));
      else
        // Set the array address taken but not escape. The escape
        // analysis will make it escape to heap when needed.
        this->array_->address_taken(false);
    }
}

// The subexpressions of an array index must be evaluated in order.
// If this is indexing into an array, rather than a slice, then only
// the index should be evaluated.  Since this is called for values on
// the left hand side of an assigment, evaluating the array, meaning
// copying the array, will cause a different array to be modified.

bool
Array_index_expression::do_must_eval_subexpressions_in_order(
    int* skip) const
{
  *skip = this->array_->type()->is_slice_type() ? 0 : 1;
  return true;
}

// Flatten array indexing: add temporary variables and bounds checks.

Expression*
Array_index_expression::do_flatten(Gogo* gogo, Named_object*,
                                   Statement_inserter* inserter)
{
  if (this->is_flattened_)
    return this;
  this->is_flattened_ = true;

  Location loc = this->location();

  if (this->is_error_expression())
    return Expression::make_error(loc);

  Expression* array = this->array_;
  Expression* start = this->start_;
  Expression* end = this->end_;
  Expression* cap = this->cap_;
  if (array->is_error_expression()
      || array->type()->is_error_type()
      || start->is_error_expression()
      || start->type()->is_error_type()
      || (end != NULL
          && (end->is_error_expression() || end->type()->is_error_type()))
      || (cap != NULL
          && (cap->is_error_expression() || cap->type()->is_error_type())))
    {
      go_assert(saw_errors());
      return Expression::make_error(loc);
    }

  Array_type* array_type = this->array_->type()->array_type();
  if (array_type == NULL)
    {
      go_assert(saw_errors());
      return Expression::make_error(loc);
    }

  Temporary_statement* temp;
  if (array_type->is_slice_type() && !array->is_multi_eval_safe())
    {
      temp = Statement::make_temporary(NULL, array, loc);
      inserter->insert(temp);
      this->array_ = Expression::make_temporary_reference(temp, loc);
      array = this->array_;
    }
  if (!start->is_multi_eval_safe())
    {
      temp = Statement::make_temporary(NULL, start, loc);
      inserter->insert(temp);
      this->start_ = Expression::make_temporary_reference(temp, loc);
      start = this->start_;
    }
  if (end != NULL
      && !end->is_nil_expression()
      && !end->is_multi_eval_safe())
    {
      temp = Statement::make_temporary(NULL, end, loc);
      inserter->insert(temp);
      this->end_ = Expression::make_temporary_reference(temp, loc);
      end = this->end_;
    }
  if (cap != NULL && !cap->is_multi_eval_safe())
    {
      temp = Statement::make_temporary(NULL, cap, loc);
      inserter->insert(temp);
      this->cap_ = Expression::make_temporary_reference(temp, loc);
      cap = this->cap_;
    }

  if (!this->needs_bounds_check_)
    return this;

  Expression* len;
  if (!array_type->is_slice_type())
    {
      len = array_type->get_length(gogo, this->array_);
      go_assert(len->is_constant());
    }
  else
    {
      len = array_type->get_length(gogo, this->array_->copy());
      temp = Statement::make_temporary(NULL, len, loc);
      inserter->insert(temp);
      len = Expression::make_temporary_reference(temp, loc);
    }

  Expression* scap = NULL;
  if (array_type->is_slice_type())
    {
      scap = array_type->get_capacity(gogo, this->array_->copy());
      temp = Statement::make_temporary(NULL, scap, loc);
      inserter->insert(temp);
      scap = Expression::make_temporary_reference(temp, loc);
    }

  // The order of bounds checks here matches the order used by the gc
  // compiler, as tested by issue30116[u].go.

  if (cap != NULL)
    {
      if (array_type->is_slice_type())
	Expression::check_bounds(cap, OPERATOR_LE, scap,
				 Runtime::PANIC_SLICE3_ACAP,
				 Runtime::PANIC_SLICE3_ACAP_U,
				 Runtime::PANIC_EXTEND_SLICE3_ACAP,
				 Runtime::PANIC_EXTEND_SLICE3_ACAP_U,
				 inserter, loc);
      else
	Expression::check_bounds(cap, OPERATOR_LE, len,
				 Runtime::PANIC_SLICE3_ALEN,
				 Runtime::PANIC_SLICE3_ALEN_U,
				 Runtime::PANIC_EXTEND_SLICE3_ALEN,
				 Runtime::PANIC_EXTEND_SLICE3_ALEN_U,
				 inserter, loc);

      Expression* start_bound = cap;
      if (end != NULL && !end->is_nil_expression())
	{
	  Expression::check_bounds(end, OPERATOR_LE, cap,
				   Runtime::PANIC_SLICE3_B,
				   Runtime::PANIC_SLICE3_B_U,
				   Runtime::PANIC_EXTEND_SLICE3_B,
				   Runtime::PANIC_EXTEND_SLICE3_B_U,
				   inserter, loc);
	  start_bound = end;
	}

      Expression::check_bounds(start, OPERATOR_LE, start_bound,
			       Runtime::PANIC_SLICE3_C,
			       Runtime::PANIC_SLICE3_C_U,
			       Runtime::PANIC_EXTEND_SLICE3_C,
			       Runtime::PANIC_EXTEND_SLICE3_C_U,
			       inserter, loc);
    }
  else if (end != NULL && !end->is_nil_expression())
    {
      if (array_type->is_slice_type())
	Expression::check_bounds(end, OPERATOR_LE, scap,
				 Runtime::PANIC_SLICE_ACAP,
				 Runtime::PANIC_SLICE_ACAP_U,
				 Runtime::PANIC_EXTEND_SLICE_ACAP,
				 Runtime::PANIC_EXTEND_SLICE_ACAP_U,
				 inserter, loc);
      else
	Expression::check_bounds(end, OPERATOR_LE, len,
				 Runtime::PANIC_SLICE_ALEN,
				 Runtime::PANIC_SLICE_ALEN_U,
				 Runtime::PANIC_EXTEND_SLICE_ALEN,
				 Runtime::PANIC_EXTEND_SLICE_ALEN_U,
				 inserter, loc);

      Expression::check_bounds(start, OPERATOR_LE, end,
			       Runtime::PANIC_SLICE_B,
			       Runtime::PANIC_SLICE_B_U,
			       Runtime::PANIC_EXTEND_SLICE_B,
			       Runtime::PANIC_EXTEND_SLICE_B_U,
			       inserter, loc);
    }
  else if (end != NULL)
    {
      Expression* start_bound;
      if (array_type->is_slice_type())
	start_bound = scap;
      else
	start_bound = len;
      Expression::check_bounds(start, OPERATOR_LE, start_bound,
			       Runtime::PANIC_SLICE_B,
			       Runtime::PANIC_SLICE_B_U,
			       Runtime::PANIC_EXTEND_SLICE_B,
			       Runtime::PANIC_EXTEND_SLICE_B_U,
			       inserter, loc);
    }
  else
    Expression::check_bounds(start, OPERATOR_LT, len,
			     Runtime::PANIC_INDEX,
			     Runtime::PANIC_INDEX_U,
			     Runtime::PANIC_EXTEND_INDEX,
			     Runtime::PANIC_EXTEND_INDEX_U,
			     inserter, loc);

  return this;
}

// Return whether this expression is addressable.

bool
Array_index_expression::do_is_addressable() const
{
  // A slice expression is not addressable.
  if (this->end_ != NULL)
    return false;

  // An index into a slice is addressable.
  if (this->array_->type()->is_slice_type())
    return true;

  // An index into an array is addressable if the array is
  // addressable.
  return this->array_->is_addressable();
}

void
Array_index_expression::do_address_taken(bool escapes)
{
  // In &x[0], if x is a slice, then x's address is not taken.
  if (!this->array_->type()->is_slice_type())
    this->array_->address_taken(escapes);
}

// Get the backend representation for an array index.

Bexpression*
Array_index_expression::do_get_backend(Translate_context* context)
{
  Array_type* array_type = this->array_->type()->array_type();
  if (array_type == NULL)
    {
      go_assert(this->array_->type()->is_error());
      return context->backend()->error_expression();
    }
  go_assert(!array_type->is_slice_type()
	    || this->array_->is_multi_eval_safe());

  Location loc = this->location();
  Gogo* gogo = context->gogo();

  Type* int_type = Type::lookup_integer_type("int");
  Btype* int_btype = int_type->get_backend(gogo);

  // Convert the length and capacity to "int".  FIXME: Do we need to
  // do this?
  Bexpression* length = NULL;
  if (this->end_ == NULL || this->end_->is_nil_expression())
    {
      Expression* len = array_type->get_length(gogo, this->array_);
      length = len->get_backend(context);
      length = gogo->backend()->convert_expression(int_btype, length, loc);
    }

  Bexpression* capacity = NULL;
  if (this->end_ != NULL)
    {
      Expression* cap = array_type->get_capacity(gogo, this->array_);
      capacity = cap->get_backend(context);
      capacity = gogo->backend()->convert_expression(int_btype, capacity, loc);
    }

  Bexpression* cap_arg = capacity;
  if (this->cap_ != NULL)
    {
      cap_arg = this->cap_->get_backend(context);
      cap_arg = gogo->backend()->convert_expression(int_btype, cap_arg, loc);
    }

  if (length == NULL)
    length = cap_arg;

  if (this->start_->type()->integer_type() == NULL
      && !Type::are_convertible(int_type, this->start_->type(), NULL))
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  Bexpression* start = this->start_->get_backend(context);
  start = gogo->backend()->convert_expression(int_btype, start, loc);

  Bfunction* bfn = context->function()->func_value()->get_decl();
  if (this->end_ == NULL)
    {
      // Simple array indexing.
      Bexpression* ret;
      if (!array_type->is_slice_type())
	{
	  Bexpression* array = this->array_->get_backend(context);
	  ret = gogo->backend()->array_index_expression(array, start, loc);
	}
      else
	{
	  Expression* valptr =
              array_type->get_value_pointer(gogo, this->array_,
                                            this->is_lvalue_);
	  Bexpression* ptr = valptr->get_backend(context);
          ptr = gogo->backend()->pointer_offset_expression(ptr, start, loc);

	  Type* ele_type = this->array_->type()->array_type()->element_type();
	  Btype* ele_btype = ele_type->get_backend(gogo);
	  ret = gogo->backend()->indirect_expression(ele_btype, ptr, false,
						     loc);
	}
      return ret;
    }

  // Slice expression.

  Bexpression* end;
  if (this->end_->is_nil_expression())
    end = length;
  else
    {
      end = this->end_->get_backend(context);
      end = gogo->backend()->convert_expression(int_btype, end, loc);
    }

  Bexpression* result_length =
    gogo->backend()->binary_expression(OPERATOR_MINUS, end, start, loc);

  Bexpression* result_capacity =
    gogo->backend()->binary_expression(OPERATOR_MINUS, cap_arg, start, loc);

  // If the new capacity is zero, don't change val.  Otherwise we can
  // get a pointer to the next object in memory, keeping it live
  // unnecessarily.  When the capacity is zero, the actual pointer
  // value doesn't matter.
  Bexpression* zero =
    Expression::make_integer_ul(0, int_type, loc)->get_backend(context);
  Bexpression* cond =
    gogo->backend()->binary_expression(OPERATOR_EQEQ, result_capacity, zero,
				       loc);
  Bexpression* offset = gogo->backend()->conditional_expression(bfn, int_btype,
								cond, zero,
								start, loc);
  Expression* valptr = array_type->get_value_pointer(gogo, this->array_,
                                                     this->is_lvalue_);
  Bexpression* val = valptr->get_backend(context);
  val = gogo->backend()->pointer_offset_expression(val, offset, loc);

  Btype* struct_btype = this->type()->get_backend(gogo);
  std::vector<Bexpression*> init;
  init.push_back(val);
  init.push_back(result_length);
  init.push_back(result_capacity);

  return gogo->backend()->constructor_expression(struct_btype, init, loc);
}

// Export an array index expression.

void
Array_index_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("(");
  this->array_->export_expression(efb);
  efb->write_c_string(")[");

  Type* old_context = efb->type_context();
  efb->set_type_context(Type::lookup_integer_type("int"));

  this->start_->export_expression(efb);
  if (this->end_ == NULL)
    go_assert(this->cap_ == NULL);
  else
    {
      efb->write_c_string(":");
      if (!this->end_->is_nil_expression())
	this->end_->export_expression(efb);
      if (this->cap_ != NULL)
	{
	  efb->write_c_string(":");
	  this->cap_->export_expression(efb);
	}
    }

  efb->set_type_context(old_context);

  efb->write_c_string("]");
}

// Dump ast representation for an array index expression.

void
Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  Index_expression::dump_index_expression(ast_dump_context, this->array_,
                                          this->start_, this->end_, this->cap_);
}

// Make an array index expression.  END and CAP may be NULL.

Expression*
Expression::make_array_index(Expression* array, Expression* start,
                             Expression* end, Expression* cap,
                             Location location)
{
  return new Array_index_expression(array, start, end, cap, location);
}

// Class String_index_expression.

// String index traversal.

int
String_index_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->string_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (Expression::traverse(&this->start_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->end_ != NULL)
    {
      if (Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

Expression*
String_index_expression::do_flatten(Gogo*, Named_object*,
                                    Statement_inserter* inserter)
{
  if (this->is_flattened_)
    return this;
  this->is_flattened_ = true;

  Location loc = this->location();

  if (this->is_error_expression())
    return Expression::make_error(loc);

  Expression* string = this->string_;
  Expression* start = this->start_;
  Expression* end = this->end_;
  if (string->is_error_expression()
      || string->type()->is_error_type()
      || start->is_error_expression()
      || start->type()->is_error_type()
      || (end != NULL
          && (end->is_error_expression() || end->type()->is_error_type())))
    {
      go_assert(saw_errors());
      return Expression::make_error(loc);
    }

  Temporary_statement* temp;
  if (!string->is_multi_eval_safe())
    {
      temp = Statement::make_temporary(NULL, string, loc);
      inserter->insert(temp);
      this->string_ = Expression::make_temporary_reference(temp, loc);
      string = this->string_;
    }
  if (!start->is_multi_eval_safe())
    {
      temp = Statement::make_temporary(NULL, start, loc);
      inserter->insert(temp);
      this->start_ = Expression::make_temporary_reference(temp, loc);
      start = this->start_;
    }
  if (end != NULL
      && !end->is_nil_expression()
      && !end->is_multi_eval_safe())
    {
      temp = Statement::make_temporary(NULL, end, loc);
      inserter->insert(temp);
      this->end_ = Expression::make_temporary_reference(temp, loc);
      end = this->end_;
    }

  Expression* len = Expression::make_string_info(string->copy(),
						 STRING_INFO_LENGTH, loc);
  temp = Statement::make_temporary(NULL, len, loc);
  inserter->insert(temp);
  len = Expression::make_temporary_reference(temp, loc);

  // The order of bounds checks here matches the order used by the gc
  // compiler, as tested by issue30116[u].go.

  if (end != NULL && !end->is_nil_expression())
    {
      Expression::check_bounds(end, OPERATOR_LE, len,
			       Runtime::PANIC_SLICE_ALEN,
			       Runtime::PANIC_SLICE_ALEN_U,
			       Runtime::PANIC_EXTEND_SLICE_ALEN,
			       Runtime::PANIC_EXTEND_SLICE_ALEN_U,
			       inserter, loc);
      Expression::check_bounds(start, OPERATOR_LE, end,
			       Runtime::PANIC_SLICE_B,
			       Runtime::PANIC_SLICE_B_U,
			       Runtime::PANIC_EXTEND_SLICE_B,
			       Runtime::PANIC_EXTEND_SLICE_B_U,
			       inserter, loc);
    }
  else if (end != NULL)
    Expression::check_bounds(start, OPERATOR_LE, len,
			     Runtime::PANIC_SLICE_B,
			     Runtime::PANIC_SLICE_B_U,
			     Runtime::PANIC_EXTEND_SLICE_B,
			     Runtime::PANIC_EXTEND_SLICE_B_U,
			     inserter, loc);
  else
    Expression::check_bounds(start, OPERATOR_LT, len,
			     Runtime::PANIC_INDEX,
			     Runtime::PANIC_INDEX_U,
			     Runtime::PANIC_EXTEND_INDEX,
			     Runtime::PANIC_EXTEND_INDEX_U,
			     inserter, loc);

  return this;
}

// Return the type of a string index.

Type*
String_index_expression::do_type()
{
  if (this->end_ == NULL)
    return Type::lookup_integer_type("byte");
  else
    return this->string_->type();
}

// Determine the type of a string index.

void
String_index_expression::do_determine_type(const Type_context*)
{
  this->string_->determine_type_no_context();

  Type_context index_context(Type::lookup_integer_type("int"), false);
  this->start_->determine_type(&index_context);
  if (this->end_ != NULL)
    this->end_->determine_type(&index_context);
}

// Check types of a string index.

void
String_index_expression::do_check_types(Gogo*)
{
  Numeric_constant nc;
  unsigned long v;
  if (this->start_->type()->integer_type() == NULL
      && !this->start_->type()->is_error()
      && (!this->start_->type()->is_abstract()
	  || !this->start_->numeric_constant_value(&nc)
	  || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
    this->report_error(_("index must be integer"));
  if (this->end_ != NULL
      && this->end_->type()->integer_type() == NULL
      && !this->end_->type()->is_error()
      && !this->end_->is_nil_expression()
      && !this->end_->is_error_expression()
      && (!this->end_->type()->is_abstract()
	  || !this->end_->numeric_constant_value(&nc)
	  || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
    this->report_error(_("slice end must be integer"));

  std::string sval;
  bool sval_valid = this->string_->string_constant_value(&sval);

  Numeric_constant inc;
  mpz_t ival;
  bool ival_valid = false;
  if (this->start_->numeric_constant_value(&inc) && inc.to_int(&ival))
    {
      ival_valid = true;
      if (mpz_sgn(ival) < 0
	  || (sval_valid
	      && (this->end_ == NULL
		  ? mpz_cmp_ui(ival, sval.length()) >= 0
		  : mpz_cmp_ui(ival, sval.length()) > 0)))
	{
	  go_error_at(this->start_->location(), "string index out of bounds");
	  this->set_is_error();
	}
    }
  if (this->end_ != NULL && !this->end_->is_nil_expression())
    {
      Numeric_constant enc;
      mpz_t eval;
      if (this->end_->numeric_constant_value(&enc) && enc.to_int(&eval))
	{
	  if (mpz_sgn(eval) < 0
	      || (sval_valid && mpz_cmp_ui(eval, sval.length()) > 0))
	    {
	      go_error_at(this->end_->location(), "string index out of bounds");
	      this->set_is_error();
	    }
	  else if (ival_valid && mpz_cmp(ival, eval) > 0)
	    this->report_error(_("inverted slice range"));
	  mpz_clear(eval);
	}
    }
  if (ival_valid)
    mpz_clear(ival);
}

// Get the backend representation for a string index.

Bexpression*
String_index_expression::do_get_backend(Translate_context* context)
{
  Location loc = this->location();
  Gogo* gogo = context->gogo();

  Type* int_type = Type::lookup_integer_type("int");

  // It is possible that an error occurred earlier because the start index
  // cannot be represented as an integer type.  In this case, we shouldn't
  // try casting the starting index into an integer since
  // Type_conversion_expression will fail to get the backend representation.
  // FIXME.
  if (this->start_->type()->integer_type() == NULL
      && !Type::are_convertible(int_type, this->start_->type(), NULL))
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  go_assert(this->string_->is_multi_eval_safe());
  go_assert(this->start_->is_multi_eval_safe());

  Expression* start = Expression::make_cast(int_type, this->start_, loc);
  Bfunction* bfn = context->function()->func_value()->get_decl();

  Expression* length =
    Expression::make_string_info(this->string_, STRING_INFO_LENGTH, loc);
  Expression* bytes =
    Expression::make_string_info(this->string_, STRING_INFO_DATA, loc);

  Bexpression* bstart = start->get_backend(context);
  Bexpression* ptr = bytes->get_backend(context);

  if (this->end_ == NULL)
    {
      ptr = gogo->backend()->pointer_offset_expression(ptr, bstart, loc);
      Btype* ubtype = Type::lookup_integer_type("uint8")->get_backend(gogo);
      return gogo->backend()->indirect_expression(ubtype, ptr, false, loc);
    }

  Expression* end = NULL;
  if (this->end_->is_nil_expression())
    end = length;
  else
    {
      go_assert(this->end_->is_multi_eval_safe());
      end = Expression::make_cast(int_type, this->end_, loc);
    }

  end = end->copy();
  Bexpression* bend = end->get_backend(context);
  Bexpression* new_length =
    gogo->backend()->binary_expression(OPERATOR_MINUS, bend, bstart, loc);

  // If the new length is zero, don't change pointer.  Otherwise we can
  // get a pointer to the next object in memory, keeping it live
  // unnecessarily.  When the length is zero, the actual pointer
  // value doesn't matter.
  Btype* int_btype = int_type->get_backend(gogo);
  Bexpression* zero =
    Expression::make_integer_ul(0, int_type, loc)->get_backend(context);
  Bexpression* cond =
    gogo->backend()->binary_expression(OPERATOR_EQEQ, new_length, zero,
                                       loc);
  Bexpression* offset =
    gogo->backend()->conditional_expression(bfn, int_btype, cond, zero,
                                            bstart, loc);

  ptr = gogo->backend()->pointer_offset_expression(ptr, offset, loc);

  Btype* str_btype = this->type()->get_backend(gogo);
  std::vector<Bexpression*> init;
  init.push_back(ptr);
  init.push_back(new_length);
  return gogo->backend()->constructor_expression(str_btype, init, loc);
}

// Export a string index expression.

void
String_index_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("(");
  this->string_->export_expression(efb);
  efb->write_c_string(")[");

  Type* old_context = efb->type_context();
  efb->set_type_context(Type::lookup_integer_type("int"));

  this->start_->export_expression(efb);
  if (this->end_ != NULL)
    {
      efb->write_c_string(":");
      if (!this->end_->is_nil_expression())
	this->end_->export_expression(efb);
    }

  efb->set_type_context(old_context);

  efb->write_c_string("]");
}

// Dump ast representation for a string index expression.

void
String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  Index_expression::dump_index_expression(ast_dump_context, this->string_,
                                          this->start_, this->end_, NULL);
}

// Make a string index expression.  END may be NULL.

Expression*
Expression::make_string_index(Expression* string, Expression* start,
			      Expression* end, Location location)
{
  return new String_index_expression(string, start, end, location);
}

// Class Map_index.

// Get the type of the map.

Map_type*
Map_index_expression::get_map_type() const
{
  Map_type* mt = this->map_->type()->map_type();
  if (mt == NULL)
    go_assert(saw_errors());
  return mt;
}

// Map index traversal.

int
Map_index_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->map_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return Expression::traverse(&this->index_, traverse);
}

// We need to pass in a pointer to the key, so flatten the index into a
// temporary variable if it isn't already.  The value pointer will be
// dereferenced and checked for nil, so flatten into a temporary to avoid
// recomputation.

Expression*
Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
				 Statement_inserter* inserter)
{
  Location loc = this->location();
  Map_type* mt = this->get_map_type();
  if (this->index()->is_error_expression()
      || this->index()->type()->is_error_type()
      || mt->is_error_type())
    {
      go_assert(saw_errors());
      return Expression::make_error(loc);
    }

  // Avoid copy for string([]byte) conversions used in map keys.
  // mapaccess doesn't keep the reference, so this is safe.
  Type_conversion_expression* ce = this->index_->conversion_expression();
  if (ce != NULL && ce->type()->is_string_type()
      && ce->expr()->type()->is_slice_type())
    ce->set_no_copy(true);

  if (!Type::are_identical(mt->key_type(), this->index_->type(),
			   Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			   NULL))
    {
      if (this->index_->type()->interface_type() != NULL
	  && !this->index_->is_multi_eval_safe())
	{
	  Temporary_statement* temp =
	    Statement::make_temporary(NULL, this->index_, loc);
	  inserter->insert(temp);
	  this->index_ = Expression::make_temporary_reference(temp, loc);
	}
      this->index_ = Expression::convert_for_assignment(gogo, mt->key_type(),
							this->index_, loc);
    }

  if (!this->index_->is_multi_eval_safe())
    {
      Temporary_statement* temp = Statement::make_temporary(NULL, this->index_,
                                                            loc);
      inserter->insert(temp);
      this->index_ = Expression::make_temporary_reference(temp, loc);
    }

  if (this->value_pointer_ == NULL)
    this->get_value_pointer(gogo);
  if (this->value_pointer_->is_error_expression()
      || this->value_pointer_->type()->is_error_type())
    return Expression::make_error(loc);
  if (!this->value_pointer_->is_multi_eval_safe())
    {
      Temporary_statement* temp =
	Statement::make_temporary(NULL, this->value_pointer_, loc);
      inserter->insert(temp);
      this->value_pointer_ = Expression::make_temporary_reference(temp, loc);
    }

  return this;
}

// Return the type of a map index.

Type*
Map_index_expression::do_type()
{
  Map_type* mt = this->get_map_type();
  if (mt == NULL)
    return Type::make_error_type();
  return mt->val_type();
}

// Fix the type of a map index.

void
Map_index_expression::do_determine_type(const Type_context*)
{
  this->map_->determine_type_no_context();
  Map_type* mt = this->get_map_type();
  Type* key_type = mt == NULL ? NULL : mt->key_type();
  Type_context subcontext(key_type, false);
  this->index_->determine_type(&subcontext);
}

// Check types of a map index.

void
Map_index_expression::do_check_types(Gogo*)
{
  std::string reason;
  Map_type* mt = this->get_map_type();
  if (mt == NULL)
    return;
  if (!Type::are_assignable(mt->key_type(), this->index_->type(), &reason))
    {
      if (reason.empty())
	this->report_error(_("incompatible type for map index"));
      else
	{
	  go_error_at(this->location(), "incompatible type for map index (%s)",
                      reason.c_str());
	  this->set_is_error();
	}
    }
}

// Add explicit type conversions.

void
Map_index_expression::do_add_conversions()
{
  Map_type* mt = this->get_map_type();
  if (mt == NULL)
    return;
  Type* lt = mt->key_type();
  Type* rt = this->index_->type();
  if (!Type::are_identical(lt, rt, 0, NULL)
      && lt->interface_type() != NULL)
    this->index_ = Expression::make_cast(lt, this->index_, this->location());
}

// Get the backend representation for a map index.

Bexpression*
Map_index_expression::do_get_backend(Translate_context* context)
{
  Map_type* type = this->get_map_type();
  if (type == NULL)
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  go_assert(this->value_pointer_ != NULL
            && this->value_pointer_->is_multi_eval_safe());

  Expression* val = Expression::make_dereference(this->value_pointer_,
                                                 NIL_CHECK_NOT_NEEDED,
                                                 this->location());
  return val->get_backend(context);
}

// Get an expression for the map index.  This returns an expression
// that evaluates to a pointer to a value.  If the key is not in the
// map, the pointer will point to a zero value.

Expression*
Map_index_expression::get_value_pointer(Gogo* gogo)
{
  if (this->value_pointer_ == NULL)
    {
      Map_type* type = this->get_map_type();
      if (type == NULL)
	{
	  go_assert(saw_errors());
	  return Expression::make_error(this->location());
	}

      Location loc = this->location();
      Expression* map_ref = this->map_;

      Expression* index_ptr = Expression::make_unary(OPERATOR_AND,
						     this->index_,
                                                     loc);

      Expression* type_expr = Expression::make_type_descriptor(type, loc);
      Expression* zero = type->fat_zero_value(gogo);
      Expression* map_index;
      if (zero == NULL)
        {
          Runtime::Function code;
          Expression* key;
          switch (type->algorithm(gogo))
            {
              case Map_type::MAP_ALG_FAST32:
              case Map_type::MAP_ALG_FAST32PTR:
                {
                  Type* uint32_type = Type::lookup_integer_type("uint32");
                  Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
                  key = Expression::make_unsafe_cast(uint32_ptr_type, index_ptr,
                                                     loc);
                  key = Expression::make_dereference(key, NIL_CHECK_NOT_NEEDED,
                                                     loc);
                  code = Runtime::MAPACCESS1_FAST32;
                  break;
                }
              case Map_type::MAP_ALG_FAST64:
              case Map_type::MAP_ALG_FAST64PTR:
                {
                  Type* uint64_type = Type::lookup_integer_type("uint64");
                  Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
                  key = Expression::make_unsafe_cast(uint64_ptr_type, index_ptr,
                                                     loc);
                  key = Expression::make_dereference(key, NIL_CHECK_NOT_NEEDED,
                                                     loc);
                  code = Runtime::MAPACCESS1_FAST64;
                  break;
                }
              case Map_type::MAP_ALG_FASTSTR:
                key = this->index_;
                code = Runtime::MAPACCESS1_FASTSTR;
                break;
              default:
                key = index_ptr;
                code = Runtime::MAPACCESS1;
                break;
            }
          map_index = Runtime::make_call(code, loc, 3,
                                         type_expr, map_ref, key);
        }
      else
        map_index = Runtime::make_call(Runtime::MAPACCESS1_FAT, loc, 4,
                                       type_expr, map_ref, index_ptr, zero);

      Type* val_type = type->val_type();
      this->value_pointer_ =
          Expression::make_unsafe_cast(Type::make_pointer_type(val_type),
                                       map_index, this->location());
    }

  return this->value_pointer_;
}

// Export a map index expression.

void
Map_index_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("(");
  this->map_->export_expression(efb);
  efb->write_c_string(")[");

  Type* old_context = efb->type_context();
  efb->set_type_context(this->get_map_type()->key_type());

  this->index_->export_expression(efb);

  efb->set_type_context(old_context);

  efb->write_c_string("]");
}

// Dump ast representation for a map index expression

void
Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  Index_expression::dump_index_expression(ast_dump_context, this->map_,
                                          this->index_, NULL, NULL);
}

// Make a map index expression.

Map_index_expression*
Expression::make_map_index(Expression* map, Expression* index,
			   Location location)
{
  return new Map_index_expression(map, index, location);
}

// Class Field_reference_expression.

// Lower a field reference expression.  There is nothing to lower, but
// this is where we generate the tracking information for fields with
// the magic go:"track" tag.

Expression*
Field_reference_expression::do_lower(Gogo* gogo, Named_object* function,
				     Statement_inserter* inserter, int)
{
  Struct_type* struct_type = this->expr_->type()->struct_type();
  if (struct_type == NULL)
    {
      // Error will be reported elsewhere.
      return this;
    }
  const Struct_field* field = struct_type->field(this->field_index_);
  if (field == NULL)
    return this;
  if (!field->has_tag())
    return this;
  if (field->tag().find("go:\"track\"") == std::string::npos)
    return this;

  // References from functions generated by the compiler don't count.
  if (function != NULL && function->func_value()->is_type_specific_function())
    return this;

  // We have found a reference to a tracked field.  Build a call to
  // the runtime function __go_fieldtrack with a string that describes
  // the field.  FIXME: We should only call this once per referenced
  // field per function, not once for each reference to the field.

  if (this->called_fieldtrack_)
    return this;
  this->called_fieldtrack_ = true;

  Location loc = this->location();

  std::string s = "fieldtrack \"";
  Named_type* nt = this->expr_->type()->unalias()->named_type();
  if (nt == NULL || nt->named_object()->package() == NULL)
    s.append(gogo->pkgpath());
  else
    s.append(nt->named_object()->package()->pkgpath());
  s.push_back('.');
  if (nt != NULL)
    s.append(Gogo::unpack_hidden_name(nt->name()));
  s.push_back('.');
  s.append(Gogo::unpack_hidden_name(field->field_name()));
  s.push_back('"');

  // We can't use a string here, because internally a string holds a
  // pointer to the actual bytes; when the linker garbage collects the
  // string, it won't garbage collect the bytes.  So we use a
  // [...]byte.

  Expression* length_expr = Expression::make_integer_ul(s.length(), NULL, loc);

  Type* byte_type = Type::lookup_integer_type("byte");
  Array_type* array_type = Type::make_array_type(byte_type, length_expr);
  array_type->set_is_array_incomparable();

  Expression_list* bytes = new Expression_list();
  for (std::string::const_iterator p = s.begin(); p != s.end(); p++)
    {
      unsigned char c = static_cast<unsigned char>(*p);
      bytes->push_back(Expression::make_integer_ul(c, NULL, loc));
    }

  Expression* e = Expression::make_composite_literal(array_type, 0, false,
						     bytes, false, loc);

  Variable* var = new Variable(array_type, e, true, false, false, loc);

  static int count;
  char buf[50];
  snprintf(buf, sizeof buf, "fieldtrack.%d", count);
  ++count;

  Named_object* no = gogo->add_variable(buf, var);
  e = Expression::make_var_reference(no, loc);
  e = Expression::make_unary(OPERATOR_AND, e, loc);

  Expression* call = Runtime::make_call(Runtime::FIELDTRACK, loc, 1, e);
  gogo->lower_expression(function, inserter, &call);
  inserter->insert(Statement::make_statement(call, false));

  // Put this function, and the global variable we just created, into
  // unique sections.  This will permit the linker to garbage collect
  // them if they are not referenced.  The effect is that the only
  // strings, indicating field references, that will wind up in the
  // executable will be those for functions that are actually needed.
  if (function != NULL)
    function->func_value()->set_in_unique_section();
  var->set_in_unique_section();

  return this;
}

// Return the type of a field reference.

Type*
Field_reference_expression::do_type()
{
  Type* type = this->expr_->type();
  if (type->is_error())
    return type;
  Struct_type* struct_type = type->struct_type();
  go_assert(struct_type != NULL);
  return struct_type->field(this->field_index_)->type();
}

// Check the types for a field reference.

void
Field_reference_expression::do_check_types(Gogo*)
{
  Type* type = this->expr_->type();
  if (type->is_error())
    return;
  Struct_type* struct_type = type->struct_type();
  go_assert(struct_type != NULL);
  go_assert(struct_type->field(this->field_index_) != NULL);
}

// Get the backend representation for a field reference.

Bexpression*
Field_reference_expression::do_get_backend(Translate_context* context)
{
  Bexpression* bstruct = this->expr_->get_backend(context);
  return context->gogo()->backend()->struct_field_expression(bstruct,
							     this->field_index_,
							     this->location());
}

// Dump ast representation for a field reference expression.

void
Field_reference_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  this->expr_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << "." <<  this->field_index_;
}

// Make a reference to a qualified identifier in an expression.

Field_reference_expression*
Expression::make_field_reference(Expression* expr, unsigned int field_index,
				 Location location)
{
  return new Field_reference_expression(expr, field_index, location);
}

// Class Interface_field_reference_expression.

// Return an expression for the pointer to the function to call.

Expression*
Interface_field_reference_expression::get_function()
{
  Expression* ref = this->expr_;
  Location loc = this->location();
  if (ref->type()->points_to() != NULL)
    ref = Expression::make_dereference(ref, NIL_CHECK_DEFAULT, loc);

  Expression* mtable =
      Expression::make_interface_info(ref, INTERFACE_INFO_METHODS, loc);
  Struct_type* mtable_type = mtable->type()->points_to()->struct_type();

  std::string name = Gogo::unpack_hidden_name(this->name_);
  unsigned int index;
  const Struct_field* field = mtable_type->find_local_field(name, &index);
  go_assert(field != NULL);

  mtable = Expression::make_dereference(mtable, NIL_CHECK_NOT_NEEDED, loc);
  return Expression::make_field_reference(mtable, index, loc);
}

// Return an expression for the first argument to pass to the interface
// function.

Expression*
Interface_field_reference_expression::get_underlying_object()
{
  Expression* expr = this->expr_;
  if (expr->type()->points_to() != NULL)
    expr = Expression::make_dereference(expr, NIL_CHECK_DEFAULT,
                                        this->location());
  return Expression::make_interface_info(expr, INTERFACE_INFO_OBJECT,
                                         this->location());
}

// Traversal.

int
Interface_field_reference_expression::do_traverse(Traverse* traverse)
{
  return Expression::traverse(&this->expr_, traverse);
}

// Lower the expression.  If this expression is not called, we need to
// evaluate the expression twice when converting to the backend
// interface.  So introduce a temporary variable if necessary.

Expression*
Interface_field_reference_expression::do_flatten(Gogo*, Named_object*,
						 Statement_inserter* inserter)
{
  if (this->expr_->is_error_expression()
      || this->expr_->type()->is_error_type())
    {
      go_assert(saw_errors());
      return Expression::make_error(this->location());
    }

  if (!this->expr_->is_multi_eval_safe())
    {
      Temporary_statement* temp =
	Statement::make_temporary(NULL, this->expr_, this->location());
      inserter->insert(temp);
      this->expr_ = Expression::make_temporary_reference(temp, this->location());
    }
  return this;
}

// Return the type of an interface field reference.

Type*
Interface_field_reference_expression::do_type()
{
  Type* expr_type = this->expr_->type();

  Type* points_to = expr_type->points_to();
  if (points_to != NULL)
    expr_type = points_to;

  Interface_type* interface_type = expr_type->interface_type();
  if (interface_type == NULL)
    return Type::make_error_type();

  const Typed_identifier* method = interface_type->find_method(this->name_);
  if (method == NULL)
    return Type::make_error_type();

  return method->type();
}

// Determine types.

void
Interface_field_reference_expression::do_determine_type(const Type_context*)
{
  this->expr_->determine_type_no_context();
}

// Check the types for an interface field reference.

void
Interface_field_reference_expression::do_check_types(Gogo*)
{
  Type* type = this->expr_->type();

  Type* points_to = type->points_to();
  if (points_to != NULL)
    type = points_to;

  Interface_type* interface_type = type->interface_type();
  if (interface_type == NULL)
    {
      if (!type->is_error_type())
	this->report_error(_("expected interface or pointer to interface"));
    }
  else
    {
      const Typed_identifier* method =
	interface_type->find_method(this->name_);
      if (method == NULL)
	{
	  go_error_at(this->location(), "method %qs not in interface",
                      Gogo::message_name(this->name_).c_str());
	  this->set_is_error();
	}
    }
}

// If an interface field reference is not simply called, then it is
// represented as a closure.  The closure will hold a single variable,
// the value of the interface on which the method should be called.
// The function will be a simple thunk that pulls the value from the
// closure and calls the method with the remaining arguments.

// Because method values are not common, we don't build all thunks for
// all possible interface methods, but instead only build them as we
// need them.  In particular, we even build them on demand for
// interface methods defined in other packages.

Interface_field_reference_expression::Interface_method_thunks
  Interface_field_reference_expression::interface_method_thunks;

// Find or create the thunk to call method NAME on TYPE.

Named_object*
Interface_field_reference_expression::create_thunk(Gogo* gogo,
						   Interface_type* type,
						   const std::string& name)
{
  std::pair<Interface_type*, Method_thunks*> val(type, NULL);
  std::pair<Interface_method_thunks::iterator, bool> ins =
    Interface_field_reference_expression::interface_method_thunks.insert(val);
  if (ins.second)
    {
      // This is the first time we have seen this interface.
      ins.first->second = new Method_thunks();
    }

  for (Method_thunks::const_iterator p = ins.first->second->begin();
       p != ins.first->second->end();
       p++)
    if (p->first == name)
      return p->second;

  Location loc = type->location();

  const Typed_identifier* method_id = type->find_method(name);
  if (method_id == NULL)
    return Named_object::make_erroneous_name(gogo->thunk_name());

  Function_type* orig_fntype = method_id->type()->function_type();
  if (orig_fntype == NULL)
    return Named_object::make_erroneous_name(gogo->thunk_name());

  Struct_field_list* sfl = new Struct_field_list();
  // The type here is wrong--it should be the C function type.  But it
  // doesn't really matter.
  Type* vt = Type::make_pointer_type(Type::make_void_type());
  sfl->push_back(Struct_field(Typed_identifier("fn", vt, loc)));
  sfl->push_back(Struct_field(Typed_identifier("val", type, loc)));
  Struct_type* st = Type::make_struct_type(sfl, loc);
  st->set_is_struct_incomparable();
  Type* closure_type = Type::make_pointer_type(st);

  Function_type* new_fntype = orig_fntype->copy_with_names();

  std::string thunk_name = gogo->thunk_name();
  Named_object* new_no = gogo->start_function(thunk_name, new_fntype,
					      false, loc);

  Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc);
  cvar->set_is_used();
  cvar->set_is_closure();
  Named_object* cp = Named_object::make_variable("$closure" + thunk_name,
						 NULL, cvar);
  new_no->func_value()->set_closure_var(cp);

  gogo->start_block(loc);

  // Field 0 of the closure is the function code pointer, field 1 is
  // the value on which to invoke the method.
  Expression* arg = Expression::make_var_reference(cp, loc);
  arg = Expression::make_dereference(arg, NIL_CHECK_NOT_NEEDED, loc);
  arg = Expression::make_field_reference(arg, 1, loc);

  Expression *ifre = Expression::make_interface_field_reference(arg, name,
								loc);

  const Typed_identifier_list* orig_params = orig_fntype->parameters();
  Expression_list* args;
  if (orig_params == NULL || orig_params->empty())
    args = NULL;
  else
    {
      const Typed_identifier_list* new_params = new_fntype->parameters();
      args = new Expression_list();
      for (Typed_identifier_list::const_iterator p = new_params->begin();
	   p != new_params->end();
	   ++p)
	{
	  Named_object* p_no = gogo->lookup(p->name(), NULL);
	  go_assert(p_no != NULL
		    && p_no->is_variable()
		    && p_no->var_value()->is_parameter());
	  args->push_back(Expression::make_var_reference(p_no, loc));
	}
    }

  Call_expression* call = Expression::make_call(ifre, args,
						orig_fntype->is_varargs(),
						loc);
  call->set_varargs_are_lowered();

  Statement* s = Statement::make_return_from_call(call, loc);
  gogo->add_statement(s);
  Block* b = gogo->finish_block(loc);
  gogo->add_block(b, loc);
  gogo->lower_block(new_no, b);
  gogo->flatten_block(new_no, b);
  gogo->finish_function(loc);

  ins.first->second->push_back(std::make_pair(name, new_no));
  return new_no;
}

// Get the backend representation for a method value.

Bexpression*
Interface_field_reference_expression::do_get_backend(Translate_context* context)
{
  Interface_type* type = this->expr_->type()->interface_type();
  if (type == NULL)
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  Named_object* thunk =
    Interface_field_reference_expression::create_thunk(context->gogo(),
						       type, this->name_);
  if (thunk->is_erroneous())
    {
      go_assert(saw_errors());
      return context->backend()->error_expression();
    }

  // FIXME: We should lower this earlier, but we can't it lower it in
  // the lowering pass because at that point we don't know whether we
  // need to create the thunk or not.  If the expression is called, we
  // don't need the thunk.

  Location loc = this->location();

  Struct_field_list* fields = new Struct_field_list();
  fields->push_back(Struct_field(Typed_identifier("fn",
						  thunk->func_value()->type(),
						  loc)));
  fields->push_back(Struct_field(Typed_identifier("val",
						  this->expr_->type(),
						  loc)));
  Struct_type* st = Type::make_struct_type(fields, loc);
  st->set_is_struct_incomparable();

  Expression_list* vals = new Expression_list();
  vals->push_back(Expression::make_func_code_reference(thunk, loc));
  vals->push_back(this->expr_);

  Expression* expr = Expression::make_struct_composite_literal(st, vals, loc);
  Bexpression* bclosure =
    Expression::make_heap_expression(expr, loc)->get_backend(context);

  Gogo* gogo = context->gogo();
  Btype* btype = this->type()->get_backend(gogo);
  bclosure = gogo->backend()->convert_expression(btype, bclosure, loc);

  Expression* nil_check =
      Expression::make_binary(OPERATOR_EQEQ, this->expr_,
                              Expression::make_nil(loc), loc);
  Bexpression* bnil_check = nil_check->get_backend(context);

  Expression* crash = Runtime::make_call(Runtime::PANIC_MEM, loc, 0);
  Bexpression* bcrash = crash->get_backend(context);

  Bfunction* bfn = context->function()->func_value()->get_decl();
  Bexpression* bcond =
      gogo->backend()->conditional_expression(bfn, NULL,
                                              bnil_check, bcrash, NULL, loc);
  Bfunction* bfunction = context->function()->func_value()->get_decl();
  Bstatement* cond_statement =
      gogo->backend()->expression_statement(bfunction, bcond);
  return gogo->backend()->compound_expression(cond_statement, bclosure, loc);
}

// Dump ast representation for an interface field reference.

void
Interface_field_reference_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  this->expr_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << "." << this->name_;
}

// Make a reference to a field in an interface.

Expression*
Expression::make_interface_field_reference(Expression* expr,
					   const std::string& field,
					   Location location)
{
  return new Interface_field_reference_expression(expr, field, location);
}

// A general selector.  This is a Parser_expression for LEFT.NAME.  It
// is lowered after we know the type of the left hand side.

class Selector_expression : public Parser_expression
{
 public:
  Selector_expression(Expression* left, const std::string& name,
		      Location location)
    : Parser_expression(EXPRESSION_SELECTOR, location),
      left_(left), name_(name)
  { }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Expression::traverse(&this->left_, traverse); }

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_copy()
  {
    return new Selector_expression(this->left_->copy(), this->name_,
				   this->location());
  }

  void
  do_dump_expression(Ast_dump_context* ast_dump_context) const;

 private:
  Expression*
  lower_method_expression(Gogo*);

  // The expression on the left hand side.
  Expression* left_;
  // The name on the right hand side.
  std::string name_;
};

// Lower a selector expression once we know the real type of the left
// hand side.

Expression*
Selector_expression::do_lower(Gogo* gogo, Named_object*, Statement_inserter*,
			      int)
{
  Expression* left = this->left_;
  if (left->is_type_expression())
    return this->lower_method_expression(gogo);
  return Type::bind_field_or_method(gogo, left->type(), left, this->name_,
				    this->location());
}

// Lower a method expression T.M or (*T).M.  We turn this into a
// function literal.

Expression*
Selector_expression::lower_method_expression(Gogo* gogo)
{
  Location location = this->location();
  Type* left_type = this->left_->type();
  Type* type = left_type;
  const std::string& name(this->name_);

  bool is_pointer;
  if (type->points_to() == NULL)
    is_pointer = false;
  else
    {
      is_pointer = true;
      type = type->points_to();
    }

  Named_type* nt = type->named_type();
  Struct_type* st = type->struct_type();
  bool is_ambiguous;
  Method* method = NULL;
  if (nt != NULL)
    method = nt->method_function(name, &is_ambiguous);
  else if (st != NULL)
    method = st->method_function(name, &is_ambiguous);
  const Typed_identifier* imethod = NULL;
  if (method == NULL && !is_pointer)
    {
      Interface_type* it = type->interface_type();
      if (it != NULL)
	imethod = it->find_method(name);
    }

  if ((method == NULL && imethod == NULL)
      || (left_type->named_type() != NULL && left_type->points_to() != NULL))
    {
      if (nt != NULL)
	{
	  if (!is_ambiguous)
	    go_error_at(location, "type %<%s%s%> has no method %<%s%>",
			is_pointer ? "*" : "",
			nt->message_name().c_str(),
			Gogo::message_name(name).c_str());
	  else
	    go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>",
			Gogo::message_name(name).c_str(),
			is_pointer ? "*" : "",
			nt->message_name().c_str());
	}
      else
	{
	  if (!is_ambiguous)
	    go_error_at(location, "type has no method %<%s%>",
			Gogo::message_name(name).c_str());
	  else
	    go_error_at(location, "method %<%s%> is ambiguous",
			Gogo::message_name(name).c_str());
	}
      return Expression::make_error(location);
    }

  if (method != NULL && !is_pointer && !method->is_value_method())
    {
      go_error_at(location, "method requires pointer (use %<(*%s).%s%>)",
                  nt->message_name().c_str(),
                  Gogo::message_name(name).c_str());
      return Expression::make_error(location);
    }

  // Build a new function type in which the receiver becomes the first
  // argument.
  Function_type* method_type;
  if (method != NULL)
    {
      method_type = method->type();
      go_assert(method_type->is_method());
    }
  else
    {
      method_type = imethod->type()->function_type();
      go_assert(method_type != NULL && !method_type->is_method());
    }

  const char* const receiver_name = "$this";
  Typed_identifier_list* parameters = new Typed_identifier_list();
  parameters->push_back(Typed_identifier(receiver_name, this->left_->type(),
					 location));

  const Typed_identifier_list* method_parameters = method_type->parameters();
  if (method_parameters != NULL)
    {
      int i = 0;
      for (Typed_identifier_list::const_iterator p = method_parameters->begin();
	   p != method_parameters->end();
	   ++p, ++i)
	{
	  if (!p->name().empty())
	    parameters->push_back(*p);
	  else
	    {
	      char buf[20];
	      snprintf(buf, sizeof buf, "$param%d", i);
	      parameters->push_back(Typed_identifier(buf, p->type(),
						     p->location()));
	    }
	}
    }

  const Typed_identifier_list* method_results = method_type->results();
  Typed_identifier_list* results;
  if (method_results == NULL)
    results = NULL;
  else
    {
      results = new Typed_identifier_list();
      for (Typed_identifier_list::const_iterator p = method_results->begin();
	   p != method_results->end();
	   ++p)
	results->push_back(*p);
    }

  Function_type* fntype = Type::make_function_type(NULL, parameters, results,
						   location);
  if (method_type->is_varargs())
    fntype->set_is_varargs();

  // We generate methods which always takes a pointer to the receiver
  // as their first argument.  If this is for a pointer type, we can
  // simply reuse the existing function.  We use an internal hack to
  // get the right type.
  // FIXME: This optimization is disabled because it doesn't yet work
  // with function descriptors when the method expression is not
  // directly called.
  if (method != NULL && is_pointer && false)
    {
      Named_object* mno = (method->needs_stub_method()
			   ? method->stub_object()
			   : method->named_object());
      Expression* f = Expression::make_func_reference(mno, NULL, location);
      f = Expression::make_cast(fntype, f, location);
      Type_conversion_expression* tce =
	static_cast<Type_conversion_expression*>(f);
      tce->set_may_convert_function_types();
      return f;
    }

  Named_object* no = gogo->start_function(gogo->thunk_name(), fntype, false,
					  location);

  Named_object* vno = gogo->lookup(receiver_name, NULL);
  go_assert(vno != NULL);
  Expression* ve = Expression::make_var_reference(vno, location);
  Expression* bm;
  if (method != NULL)
    bm = Type::bind_field_or_method(gogo, type, ve, name, location);
  else
    bm = Expression::make_interface_field_reference(ve, name, location);

  // Even though we found the method above, if it has an error type we
  // may see an error here.
  if (bm->is_error_expression())
    {
      gogo->finish_function(location);
      return bm;
    }

  Expression_list* args;
  if (parameters->size() <= 1)
    args = NULL;
  else
    {
      args = new Expression_list();
      Typed_identifier_list::const_iterator p = parameters->begin();
      ++p;
      for (; p != parameters->end(); ++p)
	{
	  vno = gogo->lookup(p->name(), NULL);
	  go_assert(vno != NULL);
	  args->push_back(Expression::make_var_reference(vno, location));
	}
    }

  gogo->start_block(location);

  Call_expression* call = Expression::make_call(bm, args,
						method_type->is_varargs(),
						location);

  Statement* s = Statement::make_return_from_call(call, location);
  gogo->add_statement(s);

  Block* b = gogo->finish_block(location);

  gogo->add_block(b, location);

  // Lower the call in case there are multiple results.
  gogo->lower_block(no, b);
  gogo->flatten_block(no, b);

  gogo->finish_function(location);

  return Expression::make_func_reference(no, NULL, location);
}

// Dump the ast for a selector expression.

void
Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->dump_expression(this->left_);
  ast_dump_context->ostream() << ".";
  ast_dump_context->ostream() << this->name_;
}

// Make a selector expression.

Expression*
Expression::make_selector(Expression* left, const std::string& name,
			  Location location)
{
  return new Selector_expression(left, name, location);
}

// Class Allocation_expression.

int
Allocation_expression::do_traverse(Traverse* traverse)
{
  return Type::traverse(this->type_, traverse);
}

Type*
Allocation_expression::do_type()
{
  return Type::make_pointer_type(this->type_);
}

void
Allocation_expression::do_check_types(Gogo*)
{
  if (!this->type_->in_heap())
    go_error_at(this->location(), "cannot heap allocate go:notinheap type");
}

// Make a copy of an allocation expression.

Expression*
Allocation_expression::do_copy()
{
  Allocation_expression* alloc =
    new Allocation_expression(this->type_->copy_expressions(),
			      this->location());
  if (this->allocate_on_stack_)
    alloc->set_allocate_on_stack();
  if (this->no_zero_)
    alloc->set_no_zero();
  return alloc;
}

// Return the backend representation for an allocation expression.

Bexpression*
Allocation_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Location loc = this->location();
  Btype* btype = this->type_->get_backend(gogo);

  if (this->allocate_on_stack_)
    {
      int64_t size;
      bool ok = this->type_->backend_type_size(gogo, &size);
      if (!ok)
        {
          go_assert(saw_errors());
          return gogo->backend()->error_expression();
        }
      Bstatement* decl;
      Named_object* fn = context->function();
      go_assert(fn != NULL);
      Bfunction* fndecl = fn->func_value()->get_or_make_decl(gogo, fn);
      Bexpression* init = (this->no_zero_
                           ? NULL
                           : gogo->backend()->zero_expression(btype));
      Bvariable* temp =
        gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
                                            init,
					    Backend::variable_address_is_taken,
					    loc, &decl);
      Bexpression* ret = gogo->backend()->var_expression(temp, loc);
      ret = gogo->backend()->address_expression(ret, loc);
      ret = gogo->backend()->compound_expression(decl, ret, loc);
      return ret;
    }

  Bexpression* space =
    gogo->allocate_memory(this->type_, loc)->get_backend(context);
  Btype* pbtype = gogo->backend()->pointer_type(btype);
  return gogo->backend()->convert_expression(pbtype, space, loc);
}

// Dump ast representation for an allocation expression.

void
Allocation_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->ostream() << "new(";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << ")";
}

// Make an allocation expression.

Expression*
Expression::make_allocation(Type* type, Location location)
{
  return new Allocation_expression(type, location);
}

// Class Ordered_value_list.

int
Ordered_value_list::traverse_vals(Traverse* traverse)
{
  if (this->vals_ != NULL)
    {
      if (this->traverse_order_ == NULL)
	{
	  if (this->vals_->traverse(traverse) == TRAVERSE_EXIT)
	    return TRAVERSE_EXIT;
	}
      else
	{
	  for (std::vector<unsigned long>::const_iterator p =
		   this->traverse_order_->begin();
	       p != this->traverse_order_->end();
	       ++p)
	    {
	      if (Expression::traverse(&this->vals_->at(*p), traverse)
		  == TRAVERSE_EXIT)
		return TRAVERSE_EXIT;
	    }
	}
    }
  return TRAVERSE_CONTINUE;
}

// Class Struct_construction_expression.

// Traversal.

int
Struct_construction_expression::do_traverse(Traverse* traverse)
{
  if (this->traverse_vals(traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Return whether this is a constant initializer.

bool
Struct_construction_expression::is_constant_struct() const
{
  if (this->vals() == NULL)
    return true;
  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    {
      if (*pv != NULL
	  && !(*pv)->is_constant()
	  && (!(*pv)->is_composite_literal()
	      || (*pv)->is_nonconstant_composite_literal()))
	return false;
    }

  const Struct_field_list* fields = this->type_->struct_type()->fields();
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf)
    {
      // There are no constant constructors for interfaces.
      if (pf->type()->interface_type() != NULL)
	return false;
    }

  return true;
}

// Return whether this is a zero value.

bool
Struct_construction_expression::do_is_zero_value() const
{
  if (this->vals() == NULL)
    return true;
  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    if (*pv != NULL && !(*pv)->is_zero_value())
      return false;

  const Struct_field_list* fields = this->type_->struct_type()->fields();
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf)
    {
      // Interface conversion may cause a zero value being converted
      // to a non-zero value, like interface{}(0).  Be conservative.
      if (pf->type()->interface_type() != NULL)
        return false;
    }

  return true;
}

// Return whether this struct can be used as a constant initializer.

bool
Struct_construction_expression::do_is_static_initializer() const
{
  if (this->vals() == NULL)
    return true;
  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    {
      if (*pv != NULL && !(*pv)->is_static_initializer())
	return false;
    }

  const Struct_field_list* fields = this->type_->struct_type()->fields();
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf)
    {
      // There are no constant constructors for interfaces.
      if (pf->type()->interface_type() != NULL)
	return false;
    }

  return true;
}

// Final type determination.

void
Struct_construction_expression::do_determine_type(const Type_context*)
{
  if (this->vals() == NULL)
    return;
  const Struct_field_list* fields = this->type_->struct_type()->fields();
  Expression_list::const_iterator pv = this->vals()->begin();
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf, ++pv)
    {
      if (pv == this->vals()->end())
	return;
      if (*pv != NULL)
	{
	  Type_context subcontext(pf->type(), false);
	  (*pv)->determine_type(&subcontext);
	}
    }
  // Extra values are an error we will report elsewhere; we still want
  // to determine the type to avoid knockon errors.
  for (; pv != this->vals()->end(); ++pv)
    (*pv)->determine_type_no_context();
}

// Check types.

void
Struct_construction_expression::do_check_types(Gogo*)
{
  if (this->vals() == NULL)
    return;

  Struct_type* st = this->type_->struct_type();
  if (this->vals()->size() > st->field_count())
    {
      this->report_error(_("too many expressions for struct"));
      return;
    }

  const Struct_field_list* fields = st->fields();
  Expression_list::const_iterator pv = this->vals()->begin();
  int i = 0;
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf, ++pv, ++i)
    {
      if (pv == this->vals()->end())
	{
	  this->report_error(_("too few expressions for struct"));
	  break;
	}

      if (*pv == NULL)
	continue;

      std::string reason;
      if (!Type::are_assignable(pf->type(), (*pv)->type(), &reason))
	{
	  if (reason.empty())
	    go_error_at((*pv)->location(),
                        "incompatible type for field %d in struct construction",
                        i + 1);
	  else
	    go_error_at((*pv)->location(),
                        ("incompatible type for field %d in "
                         "struct construction (%s)"),
                        i + 1, reason.c_str());
	  this->set_is_error();
	}
    }
  go_assert(pv == this->vals()->end());
}

// Copy.

Expression*
Struct_construction_expression::do_copy()
{
  Struct_construction_expression* ret =
    new Struct_construction_expression(this->type_->copy_expressions(),
				       (this->vals() == NULL
					? NULL
					: this->vals()->copy()),
				       this->location());
  if (this->traverse_order() != NULL)
    ret->set_traverse_order(this->traverse_order());
  return ret;
}

// Flatten a struct construction expression.  Store the values into
// temporaries if they may need interface conversion.

Expression*
Struct_construction_expression::do_flatten(Gogo*, Named_object*,
					   Statement_inserter* inserter)
{
  if (this->vals() == NULL)
    return this;

  // If this is a constant struct, we don't need temporaries.
  if (this->is_constant_struct() || this->is_static_initializer())
    return this;

  Location loc = this->location();
  const Struct_field_list* fields = this->type_->struct_type()->fields();
  Struct_field_list::const_iterator pf = fields->begin();
  for (Expression_list::iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv, ++pf)
    {
      go_assert(pf != fields->end());
      if (*pv != NULL)
	{
          if ((*pv)->is_error_expression() || (*pv)->type()->is_error_type())
            {
              go_assert(saw_errors());
              return Expression::make_error(loc);
            }
	  if (pf->type()->interface_type() != NULL
	      && !(*pv)->is_multi_eval_safe())
	    {
	      Temporary_statement* temp =
		Statement::make_temporary(NULL, *pv, loc);
	      inserter->insert(temp);
	      *pv = Expression::make_temporary_reference(temp, loc);
	    }
	}
    }
  return this;
}

// Make implicit type conversions explicit.

void
Struct_construction_expression::do_add_conversions()
{
  if (this->vals() == NULL)
    return;

  Location loc = this->location();
  const Struct_field_list* fields = this->type_->struct_type()->fields();
  Expression_list::iterator pv = this->vals()->begin();
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf, ++pv)
    {
      if (pv == this->vals()->end())
        break;
      if (*pv != NULL)
        {
          Type* ft = pf->type();
          if (!Type::are_identical(ft, (*pv)->type(), 0, NULL)
              && ft->interface_type() != NULL)
           *pv = Expression::make_cast(ft, *pv, loc);
        }
    }
}

// Return the backend representation for constructing a struct.

Bexpression*
Struct_construction_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();

  Btype* btype = this->type_->get_backend(gogo);
  if (this->vals() == NULL)
    return gogo->backend()->zero_expression(btype);

  const Struct_field_list* fields = this->type_->struct_type()->fields();
  Expression_list::const_iterator pv = this->vals()->begin();
  std::vector<Bexpression*> init;
  for (Struct_field_list::const_iterator pf = fields->begin();
       pf != fields->end();
       ++pf)
    {
      Btype* fbtype = pf->type()->get_backend(gogo);
      if (pv == this->vals()->end())
        init.push_back(gogo->backend()->zero_expression(fbtype));
      else if (*pv == NULL)
	{
          init.push_back(gogo->backend()->zero_expression(fbtype));
	  ++pv;
	}
      else
	{
          Expression* val =
              Expression::convert_for_assignment(gogo, pf->type(),
                                                 *pv, this->location());
          init.push_back(val->get_backend(context));
	  ++pv;
	}
    }
  if (this->type_->struct_type()->has_padding())
    {
      // Feed an extra value if there is a padding field.
      Btype *fbtype = Type::lookup_integer_type("uint8")->get_backend(gogo);
      init.push_back(gogo->backend()->zero_expression(fbtype));
    }
  return gogo->backend()->constructor_expression(btype, init, this->location());
}

// Export a struct construction.

void
Struct_construction_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("$convert(");
  efb->write_type(this->type_);
  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    {
      efb->write_c_string(", ");
      if (*pv != NULL)
	(*pv)->export_expression(efb);
    }
  efb->write_c_string(")");
}

// Dump ast representation of a struct construction expression.

void
Struct_construction_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << "{";
  ast_dump_context->dump_expression_list(this->vals());
  ast_dump_context->ostream() << "}";
}

// Make a struct composite literal.  This used by the thunk code.

Expression*
Expression::make_struct_composite_literal(Type* type, Expression_list* vals,
					  Location location)
{
  go_assert(type->struct_type() != NULL);
  return new Struct_construction_expression(type, vals, location);
}

// Class Array_construction_expression.

// Traversal.

int
Array_construction_expression::do_traverse(Traverse* traverse)
{
  if (this->traverse_vals(traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Return whether this is a constant initializer.

bool
Array_construction_expression::is_constant_array() const
{
  if (this->vals() == NULL)
    return true;

  // There are no constant constructors for interfaces.
  if (this->type_->array_type()->element_type()->interface_type() != NULL)
    return false;

  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    {
      if (*pv != NULL
	  && !(*pv)->is_constant()
	  && (!(*pv)->is_composite_literal()
	      || (*pv)->is_nonconstant_composite_literal()))
	return false;
    }
  return true;
}

// Return whether this is a zero value.

bool
Array_construction_expression::do_is_zero_value() const
{
  if (this->vals() == NULL)
    return true;

  // Interface conversion may cause a zero value being converted
  // to a non-zero value, like interface{}(0).  Be conservative.
  if (this->type_->array_type()->element_type()->interface_type() != NULL)
    return false;

  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    if (*pv != NULL && !(*pv)->is_zero_value())
      return false;

  return true;
}

// Return whether this can be used a constant initializer.

bool
Array_construction_expression::do_is_static_initializer() const
{
  if (this->vals() == NULL)
    return true;

  // There are no constant constructors for interfaces.
  if (this->type_->array_type()->element_type()->interface_type() != NULL)
    return false;

  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    {
      if (*pv != NULL && !(*pv)->is_static_initializer())
	return false;
    }
  return true;
}

// Final type determination.

void
Array_construction_expression::do_determine_type(const Type_context*)
{
  if (this->is_error_expression())
    {
      go_assert(saw_errors());
      return;
    }

  if (this->vals() == NULL)
    return;
  Array_type* at = this->type_->array_type();
  if (at == NULL || at->is_error() || at->element_type()->is_error())
    {
      go_assert(saw_errors());
      this->set_is_error();
      return;
    }
  Type_context subcontext(at->element_type(), false);
  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    {
      if (*pv != NULL)
	(*pv)->determine_type(&subcontext);
    }
}

// Check types.

void
Array_construction_expression::do_check_types(Gogo*)
{
  if (this->is_error_expression())
    {
      go_assert(saw_errors());
      return;
    }

  if (this->vals() == NULL)
    return;

  Array_type* at = this->type_->array_type();
  if (at == NULL || at->is_error() || at->element_type()->is_error())
    {
      go_assert(saw_errors());
      this->set_is_error();
      return;
    }
  int i = 0;
  Type* element_type = at->element_type();
  for (Expression_list::const_iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv, ++i)
    {
      if (*pv != NULL
	  && !Type::are_assignable(element_type, (*pv)->type(), NULL))
	{
	  go_error_at((*pv)->location(),
                      "incompatible type for element %d in composite literal",
                      i + 1);
	  this->set_is_error();
	}
    }
}

// Flatten an array construction expression.  Store the values into
// temporaries if they may need interface conversion.

Expression*
Array_construction_expression::do_flatten(Gogo*, Named_object*,
					   Statement_inserter* inserter)
{
  if (this->is_error_expression())
    {
      go_assert(saw_errors());
      return this;
    }

  if (this->vals() == NULL)
    return this;

  // If this is a constant array, we don't need temporaries.
  if (this->is_constant_array() || this->is_static_initializer())
    return this;

  // If the array element type is not an interface type, we don't need
  // temporaries.
  if (this->type_->array_type()->element_type()->interface_type() == NULL)
    return this;

  Location loc = this->location();
  for (Expression_list::iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    {
      if (*pv != NULL)
	{
          if ((*pv)->is_error_expression() || (*pv)->type()->is_error_type())
            {
              go_assert(saw_errors());
              return Expression::make_error(loc);
            }
	  if (!(*pv)->is_multi_eval_safe())
	    {
	      Temporary_statement* temp =
		Statement::make_temporary(NULL, *pv, loc);
	      inserter->insert(temp);
	      *pv = Expression::make_temporary_reference(temp, loc);
	    }
	}
    }
  return this;
}

// Make implicit type conversions explicit.

void
Array_construction_expression::do_add_conversions()
{
  if (this->is_error_expression())
    {
      go_assert(saw_errors());
      return;
    }

  if (this->vals() == NULL)
    return;

  Type* et = this->type_->array_type()->element_type();
  if (et->interface_type() == NULL)
    return;

  Location loc = this->location();
  for (Expression_list::iterator pv = this->vals()->begin();
       pv != this->vals()->end();
       ++pv)
    if (!Type::are_identical(et, (*pv)->type(), 0, NULL))
      *pv = Expression::make_cast(et, *pv, loc);
}

// Get a constructor expression for the array values.

Bexpression*
Array_construction_expression::get_constructor(Translate_context* context,
                                               Btype* array_btype)
{
  Type* element_type = this->type_->array_type()->element_type();

  std::vector<unsigned long> indexes;
  std::vector<Bexpression*> vals;
  Gogo* gogo = context->gogo();
  if (this->vals() != NULL)
    {
      size_t i = 0;
      std::vector<unsigned long>::const_iterator pi;
      if (this->indexes_ != NULL)
	pi = this->indexes_->begin();
      for (Expression_list::const_iterator pv = this->vals()->begin();
	   pv != this->vals()->end();
	   ++pv, ++i)
	{
	  if (this->indexes_ != NULL)
	    go_assert(pi != this->indexes_->end());

	  if (this->indexes_ == NULL)
	    indexes.push_back(i);
	  else
	    indexes.push_back(*pi);
	  if (*pv == NULL)
	    {
	      Btype* ebtype = element_type->get_backend(gogo);
	      Bexpression *zv = gogo->backend()->zero_expression(ebtype);
	      vals.push_back(zv);
	    }
	  else
	    {
              Expression* val_expr =
                  Expression::convert_for_assignment(gogo, element_type, *pv,
                                                     this->location());
	      vals.push_back(val_expr->get_backend(context));
	    }
	  if (this->indexes_ != NULL)
	    ++pi;
	}
      if (this->indexes_ != NULL)
	go_assert(pi == this->indexes_->end());
    }
  return gogo->backend()->array_constructor_expression(array_btype, indexes,
                                                       vals, this->location());
}

// Export an array construction.

void
Array_construction_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("$convert(");
  efb->write_type(this->type_);
  if (this->vals() != NULL)
    {
      std::vector<unsigned long>::const_iterator pi;
      if (this->indexes_ != NULL)
	pi = this->indexes_->begin();
      for (Expression_list::const_iterator pv = this->vals()->begin();
	   pv != this->vals()->end();
	   ++pv)
	{
	  efb->write_c_string(", ");

	  if (this->indexes_ != NULL)
	    {
	      char buf[100];
	      snprintf(buf, sizeof buf, "%lu", *pi);
	      efb->write_c_string(buf);
	      efb->write_c_string(":");
	    }

	  if (*pv != NULL)
	    (*pv)->export_expression(efb);

	  if (this->indexes_ != NULL)
	    ++pi;
	}
    }
  efb->write_c_string(")");
}

// Dump ast representation of an array construction expression.

void
Array_construction_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  Expression* length = this->type_->array_type()->length();

  ast_dump_context->ostream() << "[" ;
  if (length != NULL)
    {
      ast_dump_context->dump_expression(length);
    }
  ast_dump_context->ostream() << "]" ;
  ast_dump_context->dump_type(this->type_);
  this->dump_slice_storage_expression(ast_dump_context);
  ast_dump_context->ostream() << "{" ;
  if (this->indexes_ == NULL)
    ast_dump_context->dump_expression_list(this->vals());
  else
    {
      Expression_list::const_iterator pv = this->vals()->begin();
      for (std::vector<unsigned long>::const_iterator pi =
	     this->indexes_->begin();
	   pi != this->indexes_->end();
	   ++pi, ++pv)
	{
	  if (pi != this->indexes_->begin())
	    ast_dump_context->ostream() << ", ";
	  ast_dump_context->ostream() << *pi << ':';
	  ast_dump_context->dump_expression(*pv);
	}
    }
  ast_dump_context->ostream() << "}" ;

}

// Class Fixed_array_construction_expression.

Fixed_array_construction_expression::Fixed_array_construction_expression(
    Type* type, const std::vector<unsigned long>* indexes,
    Expression_list* vals, Location location)
  : Array_construction_expression(EXPRESSION_FIXED_ARRAY_CONSTRUCTION,
				  type, indexes, vals, location)
{ go_assert(type->array_type() != NULL && !type->is_slice_type()); }


// Copy.

Expression*
Fixed_array_construction_expression::do_copy()
{
  Type* t = this->type()->copy_expressions();
  return new Fixed_array_construction_expression(t, this->indexes(),
						 (this->vals() == NULL
						  ? NULL
						  : this->vals()->copy()),
						 this->location());
}

// Return the backend representation for constructing a fixed array.

Bexpression*
Fixed_array_construction_expression::do_get_backend(Translate_context* context)
{
  Type* type = this->type();
  Btype* btype = type->get_backend(context->gogo());
  return this->get_constructor(context, btype);
}

Expression*
Expression::make_array_composite_literal(Type* type, Expression_list* vals,
                                         Location location)
{
  go_assert(type->array_type() != NULL && !type->is_slice_type());
  return new Fixed_array_construction_expression(type, NULL, vals, location);
}

// Class Slice_construction_expression.

Slice_construction_expression::Slice_construction_expression(
  Type* type, const std::vector<unsigned long>* indexes,
  Expression_list* vals, Location location)
  : Array_construction_expression(EXPRESSION_SLICE_CONSTRUCTION,
				  type, indexes, vals, location),
    valtype_(NULL), array_val_(NULL), slice_storage_(NULL),
    storage_escapes_(true)
{
  go_assert(type->is_slice_type());

  unsigned long lenval;
  Expression* length;
  if (vals == NULL || vals->empty())
    lenval = 0;
  else
    {
      if (this->indexes() == NULL)
	lenval = vals->size();
      else
	lenval = indexes->back() + 1;
    }
  Type* int_type = Type::lookup_integer_type("int");
  length = Expression::make_integer_ul(lenval, int_type, location);
  Type* element_type = type->array_type()->element_type();
  Array_type* array_type = Type::make_array_type(element_type, length);
  array_type->set_is_array_incomparable();
  this->valtype_ = array_type;
}

// Traversal.

int
Slice_construction_expression::do_traverse(Traverse* traverse)
{
  if (this->Array_construction_expression::do_traverse(traverse)
      == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (Type::traverse(this->valtype_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->array_val_ != NULL
      && Expression::traverse(&this->array_val_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->slice_storage_ != NULL
      && Expression::traverse(&this->slice_storage_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Helper routine to create fixed array value underlying the slice literal.
// May be called during flattening, or later during do_get_backend().

Expression*
Slice_construction_expression::create_array_val()
{
  Array_type* array_type = this->type()->array_type();
  if (array_type == NULL)
    {
      go_assert(this->type()->is_error());
      return NULL;
    }

  Location loc = this->location();
  go_assert(this->valtype_ != NULL);

  Expression_list* vals = this->vals();
  return new Fixed_array_construction_expression(
      this->valtype_, this->indexes(), vals, loc);
}

// If we're previous established that the slice storage does not
// escape, then create a separate array temp val here for it. We
// need to do this as part of flattening so as to be able to insert
// the new temp statement.

Expression*
Slice_construction_expression::do_flatten(Gogo* gogo, Named_object* no,
                                          Statement_inserter* inserter)
{
  if (this->type()->array_type() == NULL)
    return NULL;

  // Base class flattening first
  this->Array_construction_expression::do_flatten(gogo, no, inserter);

  // Create a stack-allocated storage temp if storage won't escape
  if (!this->storage_escapes_
      && this->slice_storage_ == NULL
      && this->element_count() > 0)
    {
      Location loc = this->location();
      this->array_val_ = this->create_array_val();
      go_assert(this->array_val_);
      Temporary_statement* temp =
          Statement::make_temporary(this->valtype_, this->array_val_, loc);
      inserter->insert(temp);
      this->slice_storage_ = Expression::make_temporary_reference(temp, loc);
    }
  return this;
}

// When dumping a slice construction expression that has an explicit
// storeage temp, emit the temp here (if we don't do this the storage
// temp appears unused in the AST dump).

void
Slice_construction_expression::
dump_slice_storage_expression(Ast_dump_context* ast_dump_context) const
{
  if (this->slice_storage_ == NULL)
    return;
  ast_dump_context->ostream() << "storage=" ;
  ast_dump_context->dump_expression(this->slice_storage_);
}

// Copy.

Expression*
Slice_construction_expression::do_copy()
{
  return new Slice_construction_expression(this->type()->copy_expressions(),
					   this->indexes(),
					   (this->vals() == NULL
					    ? NULL
					    : this->vals()->copy()),
					   this->location());
}

// Return the backend representation for constructing a slice.

Bexpression*
Slice_construction_expression::do_get_backend(Translate_context* context)
{
  if (this->array_val_ == NULL)
    this->array_val_ = this->create_array_val();
  if (this->array_val_ == NULL)
    {
      go_assert(this->type()->is_error());
      return context->backend()->error_expression();
    }

  Location loc = this->location();

  bool is_static_initializer = this->array_val_->is_static_initializer();

  // We have to copy the initial values into heap memory if we are in
  // a function or if the values are not constants.
  bool copy_to_heap = context->function() != NULL || !is_static_initializer;

  Expression* space;

  if (this->slice_storage_ != NULL)
    {
      go_assert(!this->storage_escapes_);
      space = Expression::make_unary(OPERATOR_AND, this->slice_storage_, loc);
    }
  else if (!copy_to_heap)
    {
      // The initializer will only run once.
      space = Expression::make_unary(OPERATOR_AND, this->array_val_, loc);
      space->unary_expression()->set_is_slice_init();
    }
  else
    {
      go_assert(this->storage_escapes_ || this->element_count() == 0);
      space = Expression::make_heap_expression(this->array_val_, loc);
    }
  Array_type* at = this->valtype_->array_type();
  Type* et = at->element_type();
  space = Expression::make_unsafe_cast(Type::make_pointer_type(et),
				       space, loc);

  // Build a constructor for the slice.
  Expression* len = at->length();
  Expression* slice_val =
    Expression::make_slice_value(this->type(), space, len, len, loc);
  return slice_val->get_backend(context);
}

// Make a slice composite literal.  This is used by the type
// descriptor code.

Slice_construction_expression*
Expression::make_slice_composite_literal(Type* type, Expression_list* vals,
					 Location location)
{
  go_assert(type->is_slice_type());
  return new Slice_construction_expression(type, NULL, vals, location);
}

// Class Map_construction_expression.

// Traversal.

int
Map_construction_expression::do_traverse(Traverse* traverse)
{
  if (this->vals_ != NULL
      && this->vals_->traverse(traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Flatten constructor initializer into a temporary variable since
// we need to take its address for __go_construct_map.

Expression*
Map_construction_expression::do_flatten(Gogo* gogo, Named_object*,
                                        Statement_inserter* inserter)
{
  if (!this->is_error_expression()
      && this->vals_ != NULL
      && !this->vals_->empty()
      && this->constructor_temp_ == NULL)
    {
      Map_type* mt = this->type_->map_type();
      Type* key_type = mt->key_type();
      Type* val_type = mt->val_type();
      this->element_type_ = Type::make_builtin_struct_type(2,
                                                           "__key", key_type,
                                                           "__val", val_type);

      Expression_list* value_pairs = new Expression_list();
      Location loc = this->location();

      size_t i = 0;
      for (Expression_list::const_iterator pv = this->vals_->begin();
           pv != this->vals_->end();
           ++pv, ++i)
        {
          Expression_list* key_value_pair = new Expression_list();
          Expression* key = *pv;
          if (key->is_error_expression() || key->type()->is_error_type())
            {
              go_assert(saw_errors());
              return Expression::make_error(loc);
            }
	  if (key->type()->interface_type() != NULL
	      && !key->is_multi_eval_safe())
	    {
	      Temporary_statement* temp =
		Statement::make_temporary(NULL, key, loc);
	      inserter->insert(temp);
	      key = Expression::make_temporary_reference(temp, loc);
	    }
	  key = Expression::convert_for_assignment(gogo, key_type, key, loc);

          ++pv;
          Expression* val = *pv;
          if (val->is_error_expression() || val->type()->is_error_type())
            {
              go_assert(saw_errors());
              return Expression::make_error(loc);
            }
	  if (val->type()->interface_type() != NULL
	      && !val->is_multi_eval_safe())
	    {
	      Temporary_statement* temp =
		Statement::make_temporary(NULL, val, loc);
	      inserter->insert(temp);
	      val = Expression::make_temporary_reference(temp, loc);
	    }
	  val = Expression::convert_for_assignment(gogo, val_type, val, loc);

          key_value_pair->push_back(key);
          key_value_pair->push_back(val);
          value_pairs->push_back(
              Expression::make_struct_composite_literal(this->element_type_,
                                                        key_value_pair, loc));
        }

      Expression* element_count = Expression::make_integer_ul(i, NULL, loc);
      Array_type* ctor_type =
          Type::make_array_type(this->element_type_, element_count);
      ctor_type->set_is_array_incomparable();
      Expression* constructor =
          new Fixed_array_construction_expression(ctor_type, NULL,
                                                  value_pairs, loc);

      this->constructor_temp_ =
          Statement::make_temporary(NULL, constructor, loc);
      constructor->issue_nil_check();
      this->constructor_temp_->set_is_address_taken();
      inserter->insert(this->constructor_temp_);
    }

  return this;
}

// Final type determination.

void
Map_construction_expression::do_determine_type(const Type_context*)
{
  if (this->vals_ == NULL)
    return;

  Map_type* mt = this->type_->map_type();
  Type_context key_context(mt->key_type(), false);
  Type_context val_context(mt->val_type(), false);
  for (Expression_list::const_iterator pv = this->vals_->begin();
       pv != this->vals_->end();
       ++pv)
    {
      (*pv)->determine_type(&key_context);
      ++pv;
      (*pv)->determine_type(&val_context);
    }
}

// Check types.

void
Map_construction_expression::do_check_types(Gogo*)
{
  if (this->vals_ == NULL)
    return;

  Map_type* mt = this->type_->map_type();
  int i = 0;
  Type* key_type = mt->key_type();
  Type* val_type = mt->val_type();
  for (Expression_list::const_iterator pv = this->vals_->begin();
       pv != this->vals_->end();
       ++pv, ++i)
    {
      if (!Type::are_assignable(key_type, (*pv)->type(), NULL))
	{
	  go_error_at((*pv)->location(),
                      "incompatible type for element %d key in map construction",
                      i + 1);
	  this->set_is_error();
	}
      ++pv;
      if (!Type::are_assignable(val_type, (*pv)->type(), NULL))
	{
	  go_error_at((*pv)->location(),
                      ("incompatible type for element %d value "
                       "in map construction"),
		   i + 1);
	  this->set_is_error();
	}
    }
}

// Copy.

Expression*
Map_construction_expression::do_copy()
{
  return new Map_construction_expression(this->type_->copy_expressions(),
					 (this->vals_ == NULL
					  ? NULL
					  : this->vals_->copy()),
					 this->location());
}

// Make implicit type conversions explicit.

void
Map_construction_expression::do_add_conversions()
{
  if (this->vals_ == NULL || this->vals_->empty())
    return;

  Map_type* mt = this->type_->map_type();
  Type* kt = mt->key_type();
  Type* vt = mt->val_type();
  bool key_is_interface = (kt->interface_type() != NULL);
  bool val_is_interface = (vt->interface_type() != NULL);
  if (!key_is_interface && !val_is_interface)
    return;

  Location loc = this->location();
  for (Expression_list::iterator pv = this->vals_->begin();
       pv != this->vals_->end();
       ++pv)
    {
      if (key_is_interface &&
          !Type::are_identical(kt, (*pv)->type(), 0, NULL))
        *pv = Expression::make_cast(kt, *pv, loc);
      ++pv;
      if (val_is_interface &&
          !Type::are_identical(vt, (*pv)->type(), 0, NULL))
        *pv = Expression::make_cast(vt, *pv, loc);
    }
}

// Return the backend representation for constructing a map.

Bexpression*
Map_construction_expression::do_get_backend(Translate_context* context)
{
  if (this->is_error_expression())
    return context->backend()->error_expression();
  Location loc = this->location();

  size_t i = 0;
  Expression* ventries;
  if (this->vals_ == NULL || this->vals_->empty())
    ventries = Expression::make_nil(loc);
  else
    {
      go_assert(this->constructor_temp_ != NULL);
      i = this->vals_->size() / 2;

      Expression* ctor_ref =
          Expression::make_temporary_reference(this->constructor_temp_, loc);
      ventries = Expression::make_unary(OPERATOR_AND, ctor_ref, loc);
    }

  Map_type* mt = this->type_->map_type();
  if (this->element_type_ == NULL)
      this->element_type_ =
          Type::make_builtin_struct_type(2,
                                         "__key", mt->key_type(),
                                         "__val", mt->val_type());
  Expression* descriptor = Expression::make_type_descriptor(mt, loc);

  Type* uintptr_t = Type::lookup_integer_type("uintptr");
  Expression* count = Expression::make_integer_ul(i, uintptr_t, loc);

  Expression* entry_size =
      Expression::make_type_info(this->element_type_, TYPE_INFO_SIZE);

  unsigned int field_index;
  const Struct_field* valfield =
      this->element_type_->find_local_field("__val", &field_index);
  Expression* val_offset =
      Expression::make_struct_field_offset(this->element_type_, valfield);

  Expression* map_ctor =
      Runtime::make_call(Runtime::CONSTRUCT_MAP, loc, 5, descriptor, count,
                         entry_size, val_offset, ventries);
  return map_ctor->get_backend(context);
}

// Export an array construction.

void
Map_construction_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("$convert(");
  efb->write_type(this->type_);
  for (Expression_list::const_iterator pv = this->vals_->begin();
       pv != this->vals_->end();
       ++pv)
    {
      efb->write_c_string(", ");
      (*pv)->export_expression(efb);
    }
  efb->write_c_string(")");
}

// Dump ast representation for a map construction expression.

void
Map_construction_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "{" ;
  ast_dump_context->dump_expression_list(this->vals_, true);
  ast_dump_context->ostream() << "}";
}

// A composite literal key.  This is seen during parsing, but is not
// resolved to a named_object in case this is a composite literal of
// struct type.

class Composite_literal_key_expression : public Parser_expression
{
 public:
  Composite_literal_key_expression(const std::string& name, Location location)
    : Parser_expression(EXPRESSION_COMPOSITE_LITERAL_KEY, location),
      name_(name)
  { }

  const std::string&
  name() const
  { return this->name_; }

 protected:
  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_copy()
  {
    return new Composite_literal_key_expression(this->name_, this->location());
  }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The name.
  std::string name_;
};

// Lower a composite literal key.  We will never get here for keys in
// composite literals of struct types, because that is prevented by
// Composite_literal_expression::do_traverse.  So if we do get here,
// this must be a regular name reference after all.

Expression*
Composite_literal_key_expression::do_lower(Gogo* gogo, Named_object*,
					   Statement_inserter*, int)
{
  Named_object* no = gogo->lookup(this->name_, NULL);
  if (no == NULL)
    {
      // Gogo::lookup doesn't look in the global namespace, and names
      // used in composite literal keys aren't seen by
      // Gogo::define_global_names, so we have to look in the global
      // namespace ourselves.
      no = gogo->lookup_global(Gogo::unpack_hidden_name(this->name_).c_str());
      if (no == NULL)
	{
	  go_error_at(this->location(), "reference to undefined name %qs",
		      Gogo::message_name(this->name_).c_str());
	  return Expression::make_error(this->location());
	}
    }
  return Expression::make_unknown_reference(no, this->location());
}

// Dump a composite literal key.

void
Composite_literal_key_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "_UnknownName_(" << this->name_ << ")";
}

// Make a composite literal key.

Expression*
Expression::make_composite_literal_key(const std::string& name,
				       Location location)
{
  return new Composite_literal_key_expression(name, location);
}

// Class Composite_literal_expression.

// Traversal.

int
Composite_literal_expression::do_traverse(Traverse* traverse)
{
  if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;

  // If this is a struct composite literal with keys, then the keys
  // are field names, not expressions.  We don't want to traverse them
  // in that case.  If we do, we can give an erroneous error "variable
  // initializer refers to itself."  See bug482.go in the testsuite.
  if (this->has_keys_ && this->vals_ != NULL)
    {
      // The type may not be resolvable at this point.
      Type* type = this->type_;

      for (int depth = 0; depth < this->depth_; ++depth)
        {
	  type = type->deref();
          if (type->array_type() != NULL)
            type = type->array_type()->element_type();
          else if (type->map_type() != NULL)
            {
              if (this->key_path_[depth])
                type = type->map_type()->key_type();
              else
                type = type->map_type()->val_type();
            }
          else
            {
              // This error will be reported during lowering.
              return TRAVERSE_CONTINUE;
            }
        }
      type = type->deref();

      while (true)
	{
	  if (type->classification() == Type::TYPE_NAMED)
	    type = type->named_type()->real_type();
	  else if (type->classification() == Type::TYPE_FORWARD)
	    {
	      Type* t = type->forwarded();
	      if (t == type)
		break;
	      type = t;
	    }
	  else
	    break;
	}

      if (type->classification() == Type::TYPE_STRUCT)
	{
	  Expression_list::iterator p = this->vals_->begin();
	  while (p != this->vals_->end())
	    {
	      // Skip key.
	      ++p;
	      go_assert(p != this->vals_->end());
	      if (Expression::traverse(&*p, traverse) == TRAVERSE_EXIT)
		return TRAVERSE_EXIT;
	      ++p;
	    }
	  return TRAVERSE_CONTINUE;
	}
    }

  if (this->vals_ != NULL)
    return this->vals_->traverse(traverse);

  return TRAVERSE_CONTINUE;
}

// Lower a generic composite literal into a specific version based on
// the type.

Expression*
Composite_literal_expression::do_lower(Gogo* gogo, Named_object* function,
				       Statement_inserter* inserter, int)
{
  Type* type = this->type_;

  for (int depth = 0; depth < this->depth_; ++depth)
    {
      type = type->deref();
      if (type->array_type() != NULL)
	type = type->array_type()->element_type();
      else if (type->map_type() != NULL)
        {
          if (this->key_path_[depth])
            type = type->map_type()->key_type();
          else
            type = type->map_type()->val_type();
        }
      else
	{
	  if (!type->is_error())
	    go_error_at(this->location(),
                        ("may only omit types within composite literals "
                         "of slice, array, or map type"));
	  return Expression::make_error(this->location());
	}
    }

  Type *pt = type->points_to();
  bool is_pointer = false;
  if (pt != NULL)
    {
      is_pointer = true;
      type = pt;
    }

  Expression* ret;
  if (type->is_error())
    return Expression::make_error(this->location());
  else if (type->struct_type() != NULL)
    ret = this->lower_struct(gogo, type);
  else if (type->array_type() != NULL)
    ret = this->lower_array(type);
  else if (type->map_type() != NULL)
    ret = this->lower_map(gogo, function, inserter, type);
  else
    {
      go_error_at(this->location(),
                  ("expected struct, slice, array, or map type "
                   "for composite literal"));
      return Expression::make_error(this->location());
    }

  if (is_pointer)
    ret = Expression::make_heap_expression(ret, this->location());

  return ret;
}

// Lower a struct composite literal.

Expression*
Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
{
  Location location = this->location();
  Struct_type* st = type->struct_type();
  if (this->vals_ == NULL || !this->has_keys_)
    {
      if (this->vals_ != NULL
	  && !this->vals_->empty()
	  && type->named_type() != NULL
	  && type->named_type()->named_object()->package() != NULL)
	{
	  for (Struct_field_list::const_iterator pf = st->fields()->begin();
	       pf != st->fields()->end();
	       ++pf)
	    {
	      if (Gogo::is_hidden_name(pf->field_name())
		  || pf->is_embedded_builtin(gogo))
		go_error_at(this->location(),
                            "assignment of unexported field %qs in %qs literal",
                            Gogo::message_name(pf->field_name()).c_str(),
                            type->named_type()->message_name().c_str());
	    }
	}

      return new Struct_construction_expression(type, this->vals_, location);
    }

  size_t field_count = st->field_count();
  std::vector<Expression*> vals(field_count);
  std::vector<unsigned long>* traverse_order = new(std::vector<unsigned long>);
  Expression_list::const_iterator p = this->vals_->begin();
  Expression* external_expr = NULL;
  const Named_object* external_no = NULL;
  while (p != this->vals_->end())
    {
      Expression* name_expr = *p;

      ++p;
      go_assert(p != this->vals_->end());
      Expression* val = *p;

      ++p;

      if (name_expr == NULL)
	{
	  go_error_at(val->location(),
                      "mixture of field and value initializers");
	  return Expression::make_error(location);
	}

      bool bad_key = false;
      std::string name;
      const Named_object* no = NULL;
      switch (name_expr->classification())
	{
	case EXPRESSION_COMPOSITE_LITERAL_KEY:
	  name =
	    static_cast<Composite_literal_key_expression*>(name_expr)->name();
	  break;

	case EXPRESSION_UNKNOWN_REFERENCE:
	  name = name_expr->unknown_expression()->name();
	  if (type->named_type() != NULL)
	    {
	      // If the named object found for this field name comes from a
	      // different package than the struct it is a part of, do not count
	      // this incorrect lookup as a usage of the object's package.
	      no = name_expr->unknown_expression()->named_object();
	      if (no->package() != NULL
		  && no->package() != type->named_type()->named_object()->package())
		no->package()->forget_usage(name_expr);
	    }
	  break;

	case EXPRESSION_CONST_REFERENCE:
	  no = static_cast<Const_expression*>(name_expr)->named_object();
	  break;

	case EXPRESSION_TYPE:
	  {
	    Type* t = name_expr->type();
	    Named_type* nt = t->named_type();
	    if (nt == NULL)
	      bad_key = true;
	    else
	      no = nt->named_object();
	  }
	  break;

	case EXPRESSION_VAR_REFERENCE:
	  no = name_expr->var_expression()->named_object();
	  break;

	case EXPRESSION_ENCLOSED_VAR_REFERENCE:
	  no = name_expr->enclosed_var_expression()->variable();
	  break;

	case EXPRESSION_FUNC_REFERENCE:
	  no = name_expr->func_expression()->named_object();
	  break;

	default:
	  bad_key = true;
	  break;
	}
      if (bad_key)
	{
	  go_error_at(name_expr->location(), "expected struct field name");
	  return Expression::make_error(location);
	}

      if (no != NULL)
	{
	  if (no->package() != NULL && external_expr == NULL)
	    {
	      external_expr = name_expr;
	      external_no = no;
	    }

	  name = no->name();

	  // A predefined name won't be packed.  If it starts with a
	  // lower case letter we need to check for that case, because
	  // the field name will be packed.  FIXME.
	  if (!Gogo::is_hidden_name(name)
	      && name[0] >= 'a'
	      && name[0] <= 'z')
	    {
	      Named_object* gno = gogo->lookup_global(name.c_str());
	      if (gno == no)
		name = gogo->pack_hidden_name(name, false);
	    }
	}

      unsigned int index;
      const Struct_field* sf = st->find_local_field(name, &index);
      if (sf == NULL)
	{
	  go_error_at(name_expr->location(), "unknown field %qs in %qs",
                      Gogo::message_name(name).c_str(),
                      (type->named_type() != NULL
                       ? type->named_type()->message_name().c_str()
                       : "unnamed struct"));
	  return Expression::make_error(location);
	}
      if (vals[index] != NULL)
	{
	  go_error_at(name_expr->location(),
                      "duplicate value for field %qs in %qs",
                      Gogo::message_name(name).c_str(),
                      (type->named_type() != NULL
                       ? type->named_type()->message_name().c_str()
                       : "unnamed struct"));
	  return Expression::make_error(location);
	}

      if (type->named_type() != NULL
	  && type->named_type()->named_object()->package() != NULL
	  && (Gogo::is_hidden_name(sf->field_name())
	      || sf->is_embedded_builtin(gogo)))
	go_error_at(name_expr->location(),
                    "assignment of unexported field %qs in %qs literal",
                    Gogo::message_name(sf->field_name()).c_str(),
                    type->named_type()->message_name().c_str());

      vals[index] = val;
      traverse_order->push_back(static_cast<unsigned long>(index));
    }

  if (!this->all_are_names_)
    {
      // This is a weird case like bug462 in the testsuite.
      if (external_expr == NULL)
	go_error_at(this->location(), "unknown field in %qs literal",
                    (type->named_type() != NULL
                     ? type->named_type()->message_name().c_str()
                     : "unnamed struct"));
      else
	go_error_at(external_expr->location(), "unknown field %qs in %qs",
                    external_no->message_name().c_str(),
                    (type->named_type() != NULL
                     ? type->named_type()->message_name().c_str()
                     : "unnamed struct"));
      return Expression::make_error(location);
    }

  Expression_list* list = new Expression_list;
  list->reserve(field_count);
  for (size_t i = 0; i < field_count; ++i)
    list->push_back(vals[i]);

  Struct_construction_expression* ret =
    new Struct_construction_expression(type, list, location);
  ret->set_traverse_order(traverse_order);
  return ret;
}

// Index/value/traversal-order triple.

struct IVT_triple {
  unsigned long index;
  unsigned long traversal_order;
  Expression* expr;
  IVT_triple(unsigned long i, unsigned long to, Expression *e)
      : index(i), traversal_order(to), expr(e) { }
  bool operator<(const IVT_triple& other) const
  { return this->index < other.index; }
};

// Lower an array composite literal.

Expression*
Composite_literal_expression::lower_array(Type* type)
{
  Location location = this->location();
  if (this->vals_ == NULL || !this->has_keys_)
    return this->make_array(type, NULL, this->vals_);

  std::vector<unsigned long>* indexes = new std::vector<unsigned long>;
  indexes->reserve(this->vals_->size());
  bool indexes_out_of_order = false;
  Expression_list* vals = new Expression_list();
  vals->reserve(this->vals_->size());
  unsigned long index = 0;
  Expression_list::const_iterator p = this->vals_->begin();
  while (p != this->vals_->end())
    {
      Expression* index_expr = *p;

      ++p;
      go_assert(p != this->vals_->end());
      Expression* val = *p;

      ++p;

      if (index_expr == NULL)
	{
	  if (std::find(indexes->begin(), indexes->end(), index)
	      != indexes->end())
	    {
	      go_error_at(val->location(),
			  "duplicate value for index %lu", index);
	      return Expression::make_error(location);
	    }
	  if (!indexes->empty())
	    indexes->push_back(index);
	}
      else
	{
	  if (indexes->empty() && !vals->empty())
	    {
	      for (size_t i = 0; i < vals->size(); ++i)
		indexes->push_back(i);
	    }

	  Numeric_constant nc;
	  if (!index_expr->numeric_constant_value(&nc))
	    {
	      go_error_at(index_expr->location(),
                          "index expression is not integer constant");
	      return Expression::make_error(location);
	    }

	  switch (nc.to_unsigned_long(&index))
	    {
	    case Numeric_constant::NC_UL_VALID:
	      break;
	    case Numeric_constant::NC_UL_NOTINT:
	      go_error_at(index_expr->location(),
                          "index expression is not integer constant");
	      return Expression::make_error(location);
	    case Numeric_constant::NC_UL_NEGATIVE:
	      go_error_at(index_expr->location(),
                          "index expression is negative");
	      return Expression::make_error(location);
	    case Numeric_constant::NC_UL_BIG:
	      go_error_at(index_expr->location(), "index value overflow");
	      return Expression::make_error(location);
	    default:
	      go_unreachable();
	    }

	  Named_type* ntype = Type::lookup_integer_type("int");
	  Integer_type* inttype = ntype->integer_type();
	  if (sizeof(index) <= static_cast<size_t>(inttype->bits() * 8)
	      && index >> (inttype->bits() - 1) != 0)
	    {
	      go_error_at(index_expr->location(), "index value overflow");
	      return Expression::make_error(location);
	    }

	  if (std::find(indexes->begin(), indexes->end(), index)
	      != indexes->end())
	    {
	      go_error_at(index_expr->location(),
                          "duplicate value for index %lu",
                          index);
	      return Expression::make_error(location);
	    }

	  if (!indexes->empty() && index < indexes->back())
	    indexes_out_of_order = true;

	  indexes->push_back(index);
	}

      vals->push_back(val);

      ++index;
    }

  if (indexes->empty())
    {
      delete indexes;
      indexes = NULL;
    }

  std::vector<unsigned long>* traverse_order = NULL;
  if (indexes_out_of_order)
    {
      typedef std::vector<IVT_triple> V;

      V v;
      v.reserve(indexes->size());
      std::vector<unsigned long>::const_iterator pi = indexes->begin();
      unsigned long torder = 0;
      for (Expression_list::const_iterator pe = vals->begin();
	   pe != vals->end();
	   ++pe, ++pi, ++torder)
	v.push_back(IVT_triple(*pi, torder, *pe));

      std::sort(v.begin(), v.end());

      delete indexes;
      delete vals;

      indexes = new std::vector<unsigned long>();
      indexes->reserve(v.size());
      vals = new Expression_list();
      vals->reserve(v.size());
      traverse_order = new std::vector<unsigned long>();
      traverse_order->reserve(v.size());

      for (V::const_iterator pv = v.begin(); pv != v.end(); ++pv)
	{
	  indexes->push_back(pv->index);
	  vals->push_back(pv->expr);
	  traverse_order->push_back(pv->traversal_order);
	}
    }

  Expression* ret = this->make_array(type, indexes, vals);
  Array_construction_expression* ace = ret->array_literal();
  if (ace != NULL && traverse_order != NULL)
    ace->set_traverse_order(traverse_order);
  return ret;
}

// Actually build the array composite literal. This handles
// [...]{...}.

Expression*
Composite_literal_expression::make_array(
    Type* type,
    const std::vector<unsigned long>* indexes,
    Expression_list* vals)
{
  Location location = this->location();
  Array_type* at = type->array_type();

  if (at->length() != NULL && at->length()->is_nil_expression())
    {
      size_t size;
      if (vals == NULL)
	size = 0;
      else if (indexes != NULL)
	size = indexes->back() + 1;
      else
	{
	  size = vals->size();
	  Integer_type* it = Type::lookup_integer_type("int")->integer_type();
	  if (sizeof(size) <= static_cast<size_t>(it->bits() * 8)
	      && size >> (it->bits() - 1) != 0)
	    {
	      go_error_at(location, "too many elements in composite literal");
	      return Expression::make_error(location);
	    }
	}

      Expression* elen = Expression::make_integer_ul(size, NULL, location);
      at = Type::make_array_type(at->element_type(), elen);
      type = at;
    }
  else if (at->length() != NULL
	   && !at->length()->is_error_expression()
	   && this->vals_ != NULL)
    {
      Numeric_constant nc;
      unsigned long val;
      if (at->length()->numeric_constant_value(&nc)
	  && nc.to_unsigned_long(&val) == Numeric_constant::NC_UL_VALID)
	{
	  if (indexes == NULL)
	    {
	      if (this->vals_->size() > val)
		{
		  go_error_at(location,
                              "too many elements in composite literal");
		  return Expression::make_error(location);
		}
	    }
	  else
	    {
	      unsigned long max = indexes->back();
	      if (max >= val)
		{
		  go_error_at(location,
                              ("some element keys in composite literal "
                               "are out of range"));
		  return Expression::make_error(location);
		}
	    }
	}
    }

  if (at->length() != NULL)
    return new Fixed_array_construction_expression(type, indexes, vals,
						   location);
  else
    return new Slice_construction_expression(type, indexes, vals, location);
}

// Lower a map composite literal.

Expression*
Composite_literal_expression::lower_map(Gogo* gogo, Named_object* function,
					Statement_inserter* inserter,
					Type* type)
{
  Location location = this->location();
  Unordered_map(unsigned int, std::vector<Expression*>) st;
  Unordered_map(unsigned int, std::vector<Expression*>) nt;
  if (this->vals_ != NULL)
    {
      if (!this->has_keys_)
	{
	  go_error_at(location, "map composite literal must have keys");
	  return Expression::make_error(location);
	}

      for (Expression_list::iterator p = this->vals_->begin();
	   p != this->vals_->end();
	   p += 2)
	{
	  if (*p == NULL)
	    {
	      ++p;
	      go_error_at((*p)->location(),
                          ("map composite literal must "
                           "have keys for every value"));
	      return Expression::make_error(location);
	    }
	  // Make sure we have lowered the key; it may not have been
	  // lowered in order to handle keys for struct composite
	  // literals.  Lower it now to get the right error message.
	  if ((*p)->unknown_expression() != NULL)
	    {
	      gogo->lower_expression(function, inserter, &*p);
	      go_assert((*p)->is_error_expression());
	      return Expression::make_error(location);
	    }
	  // Check if there are duplicate constant keys.
	  if (!(*p)->is_constant())
	    continue;
	  std::string sval;
	  Numeric_constant nval;
	  if ((*p)->string_constant_value(&sval)) // Check string keys.
	    {
	      unsigned int h = Gogo::hash_string(sval, 0);
	      // Search the index h in the hash map.
	      Unordered_map(unsigned int, std::vector<Expression*>)::iterator mit;
	      mit = st.find(h);
	      if (mit == st.end())
		{
		  // No duplicate since h is a new index.
		  // Create a new vector indexed by h and add it to the hash map.
		  std::vector<Expression*> l;
		  l.push_back(*p);
		  std::pair<unsigned int, std::vector<Expression*> > val(h, l);
		  st.insert(val);
		}
	      else
		{
		  // Do further check since index h already exists.
		  for (std::vector<Expression*>::iterator lit =
			   mit->second.begin();
		       lit != mit->second.end();
		       lit++)
		    {
		      std::string s;
		      bool ok = (*lit)->string_constant_value(&s);
		      go_assert(ok);
		      if (s == sval)
			{
			  go_error_at((*p)->location(), ("duplicate key "
				      "in map literal"));
			  return Expression::make_error(location);
			}
		    }
		  // Add this new string key to the vector indexed by h.
		  mit->second.push_back(*p);
		}
	    }
	  else if ((*p)->numeric_constant_value(&nval)) // Check numeric keys.
	    {
	      unsigned int h = nval.hash(0);
	      Unordered_map(unsigned int, std::vector<Expression*>)::iterator mit;
	      mit = nt.find(h);
	      if (mit == nt.end())
		{
		  // No duplicate since h is a new code.
		  // Create a new vector indexed by h and add it to the hash map.
		  std::vector<Expression*> l;
		  l.push_back(*p);
		  std::pair<unsigned int, std::vector<Expression*> > val(h, l);
		  nt.insert(val);
		}
	      else
		{
		  // Do further check since h already exists.
		  for (std::vector<Expression*>::iterator lit =
			   mit->second.begin();
		       lit != mit->second.end();
		       lit++)
		    {
		      Numeric_constant rval;
		      bool ok = (*lit)->numeric_constant_value(&rval);
		      go_assert(ok);
		      if (nval.equals(rval))
			{
			  go_error_at((*p)->location(),
				      "duplicate key in map literal");
			  return Expression::make_error(location);
			}
		    }
		  // Add this new numeric key to the vector indexed by h.
		  mit->second.push_back(*p);
		}
	    }
	}
    }

  return new Map_construction_expression(type, this->vals_, location);
}

// Copy.

Expression*
Composite_literal_expression::do_copy()
{
  Composite_literal_expression* ret =
    new Composite_literal_expression(this->type_->copy_expressions(),
				     this->depth_, this->has_keys_,
				     (this->vals_ == NULL
				      ? NULL
				      : this->vals_->copy()),
				     this->all_are_names_,
				     this->location());
  ret->key_path_ = this->key_path_;
  return ret;
}

// Dump ast representation for a composite literal expression.

void
Composite_literal_expression::do_dump_expression(
                               Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "composite(";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << ", {";
  ast_dump_context->dump_expression_list(this->vals_, this->has_keys_);
  ast_dump_context->ostream() << "})";
}

// Make a composite literal expression.

Expression*
Expression::make_composite_literal(Type* type, int depth, bool has_keys,
				   Expression_list* vals, bool all_are_names,
				   Location location)
{
  return new Composite_literal_expression(type, depth, has_keys, vals,
					  all_are_names, location);
}

// Return whether this expression is a composite literal.

bool
Expression::is_composite_literal() const
{
  switch (this->classification_)
    {
    case EXPRESSION_COMPOSITE_LITERAL:
    case EXPRESSION_STRUCT_CONSTRUCTION:
    case EXPRESSION_FIXED_ARRAY_CONSTRUCTION:
    case EXPRESSION_SLICE_CONSTRUCTION:
    case EXPRESSION_MAP_CONSTRUCTION:
      return true;
    default:
      return false;
    }
}

// Return whether this expression is a composite literal which is not
// constant.

bool
Expression::is_nonconstant_composite_literal() const
{
  switch (this->classification_)
    {
    case EXPRESSION_STRUCT_CONSTRUCTION:
      {
	const Struct_construction_expression *psce =
	  static_cast<const Struct_construction_expression*>(this);
	return !psce->is_constant_struct();
      }
    case EXPRESSION_FIXED_ARRAY_CONSTRUCTION:
      {
	const Fixed_array_construction_expression *pace =
	  static_cast<const Fixed_array_construction_expression*>(this);
	return !pace->is_constant_array();
      }
    case EXPRESSION_SLICE_CONSTRUCTION:
      {
	const Slice_construction_expression *pace =
	  static_cast<const Slice_construction_expression*>(this);
	return !pace->is_constant_array();
      }
    case EXPRESSION_MAP_CONSTRUCTION:
      return true;
    default:
      return false;
    }
}

// Return true if this is a variable or temporary_variable.

bool
Expression::is_variable() const
{
  switch (this->classification_)
    {
    case EXPRESSION_VAR_REFERENCE:
    case EXPRESSION_TEMPORARY_REFERENCE:
    case EXPRESSION_SET_AND_USE_TEMPORARY:
    case EXPRESSION_ENCLOSED_VAR_REFERENCE:
      return true;
    default:
      return false;
    }
}

// Return true if this is a reference to a local variable.

bool
Expression::is_local_variable() const
{
  const Var_expression* ve = this->var_expression();
  if (ve == NULL)
    return false;
  const Named_object* no = ve->named_object();
  return (no->is_result_variable()
	  || (no->is_variable() && !no->var_value()->is_global()));
}

// Return true if multiple evaluations are OK.

bool
Expression::is_multi_eval_safe()
{
  switch (this->classification_)
    {
    case EXPRESSION_VAR_REFERENCE:
      {
	// A variable is a simple reference if not stored in the heap.
	const Named_object* no = this->var_expression()->named_object();
	if (no->is_variable())
	  return !no->var_value()->is_in_heap();
	else if (no->is_result_variable())
	  return !no->result_var_value()->is_in_heap();
	else
	  go_unreachable();
      }

    case EXPRESSION_TEMPORARY_REFERENCE:
      return true;

    default:
      break;
    }

  if (!this->is_constant())
    return false;

  // Only numeric and boolean constants are really multi-evaluation
  // safe.  We don't want multiple copies of string constants.
  Type* type = this->type();
  return type->is_numeric_type() || type->is_boolean_type();
}

const Named_object*
Expression::named_constant() const
{
  if (this->classification() != EXPRESSION_CONST_REFERENCE)
    return NULL;
  const Const_expression* ce = static_cast<const Const_expression*>(this);
  return ce->named_object();
}

// Class Type_guard_expression.

// Traversal.

int
Type_guard_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->expr_, traverse) == TRAVERSE_EXIT
      || Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

Expression*
Type_guard_expression::do_flatten(Gogo*, Named_object*,
                                  Statement_inserter* inserter)
{
  if (this->expr_->is_error_expression()
      || this->expr_->type()->is_error_type())
    {
      go_assert(saw_errors());
      return Expression::make_error(this->location());
    }

  if (!this->expr_->is_multi_eval_safe())
    {
      Temporary_statement* temp = Statement::make_temporary(NULL, this->expr_,
                                                            this->location());
      inserter->insert(temp);
      this->expr_ =
          Expression::make_temporary_reference(temp, this->location());
    }
  return this;
}

// Check types of a type guard expression.  The expression must have
// an interface type, but the actual type conversion is checked at run
// time.

void
Type_guard_expression::do_check_types(Gogo*)
{
  Type* expr_type = this->expr_->type();
  if (expr_type->interface_type() == NULL)
    {
      if (!expr_type->is_error() && !this->type_->is_error())
	this->report_error(_("type assertion only valid for interface types"));
      this->set_is_error();
    }
  else if (this->type_->interface_type() == NULL)
    {
      std::string reason;
      if (!expr_type->interface_type()->implements_interface(this->type_,
							     &reason))
	{
	  if (!this->type_->is_error())
	    {
	      if (reason.empty())
		this->report_error(_("impossible type assertion: "
				     "type does not implement interface"));
	      else
		go_error_at(this->location(),
                            ("impossible type assertion: "
                             "type does not implement interface (%s)"),
                            reason.c_str());
	    }
	  this->set_is_error();
	}
    }
}

// Copy.

Expression*
Type_guard_expression::do_copy()
{
  return new Type_guard_expression(this->expr_->copy(),
				   this->type_->copy_expressions(),
				   this->location());
}

// Return the backend representation for a type guard expression.

Bexpression*
Type_guard_expression::do_get_backend(Translate_context* context)
{
  Expression* conversion;
  if (this->type_->interface_type() != NULL)
    conversion =
        Expression::convert_interface_to_interface(this->type_, this->expr_,
                                                   true, this->location());
  else
    conversion =
        Expression::convert_for_assignment(context->gogo(), this->type_,
                                           this->expr_, this->location());

  Gogo* gogo = context->gogo();
  Btype* bt = this->type_->get_backend(gogo);
  Bexpression* bexpr = conversion->get_backend(context);
  return gogo->backend()->convert_expression(bt, bexpr, this->location());
}

// Dump ast representation for a type guard expression.

void
Type_guard_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
    const
{
  this->expr_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() <<  ".";
  ast_dump_context->dump_type(this->type_);
}

// Make a type guard expression.

Expression*
Expression::make_type_guard(Expression* expr, Type* type,
			    Location location)
{
  return new Type_guard_expression(expr, type, location);
}

// Class Heap_expression.

// Return the type of the expression stored on the heap.

Type*
Heap_expression::do_type()
{ return Type::make_pointer_type(this->expr_->type()); }

// Return the backend representation for allocating an expression on the heap.

Bexpression*
Heap_expression::do_get_backend(Translate_context* context)
{
  Type* etype = this->expr_->type();
  if (this->expr_->is_error_expression() || etype->is_error())
    return context->backend()->error_expression();

  Location loc = this->location();
  Gogo* gogo = context->gogo();
  Btype* btype = this->type()->get_backend(gogo);

  Expression* alloc = Expression::make_allocation(etype, loc);
  if (this->allocate_on_stack_)
    alloc->allocation_expression()->set_allocate_on_stack();
  Bexpression* space = alloc->get_backend(context);

  Bstatement* decl;
  Named_object* fn = context->function();
  go_assert(fn != NULL);
  Bfunction* fndecl = fn->func_value()->get_or_make_decl(gogo, fn);
  Bvariable* space_temp =
    gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
					space,
					Backend::variable_address_is_taken,
					loc, &decl);
  Btype* expr_btype = etype->get_backend(gogo);

  Bexpression* bexpr = this->expr_->get_backend(context);

  // If this assignment needs a write barrier, call typedmemmove.  We
  // don't do this in the write barrier pass because in some cases
  // backend conversion can introduce new Heap_expression values.
  Bstatement* assn;
  if (!etype->has_pointer() || this->allocate_on_stack_)
    {
      space = gogo->backend()->var_expression(space_temp, loc);
      Bexpression* ref =
	gogo->backend()->indirect_expression(expr_btype, space, true, loc);
      assn = gogo->backend()->assignment_statement(fndecl, ref, bexpr, loc);
    }
  else
    {
      Bstatement* edecl;
      Bvariable* btemp =
	gogo->backend()->temporary_variable(fndecl, context->bblock(),
					    expr_btype, bexpr,
					    Backend::variable_address_is_taken,
					    loc, &edecl);
      Bexpression* btempref = gogo->backend()->var_expression(btemp,
							      loc);
      space = gogo->backend()->var_expression(space_temp, loc);
      Type* etype_ptr = Type::make_pointer_type(etype);
      Expression* elhs = Expression::make_backend(space, etype_ptr, loc);
      Expression* erhs;
      Expression* call;
      if (etype->is_direct_iface_type())
        {
          // Single pointer.
          Type* uintptr_type = Type::lookup_integer_type("uintptr");
          erhs = Expression::make_backend(btempref, etype, loc);
          erhs = Expression::unpack_direct_iface(erhs, loc);
          erhs = Expression::make_unsafe_cast(uintptr_type, erhs, loc);
          call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2,
                                    elhs, erhs);
        }
      else
        {
          Expression* td = Expression::make_type_descriptor(etype, loc);
          Bexpression* addr =
            gogo->backend()->address_expression(btempref, loc);
          erhs = Expression::make_backend(addr, etype_ptr, loc);
          call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
                                    td, elhs, erhs);
        }
      Statement* cs = Statement::make_statement(call, false);

      space = gogo->backend()->var_expression(space_temp, loc);
      Bexpression* ref =
        gogo->backend()->indirect_expression(expr_btype, space, true, loc);
      Expression* eref = Expression::make_backend(ref, etype, loc);
      btempref = gogo->backend()->var_expression(btemp, loc);
      erhs = Expression::make_backend(btempref, etype, loc);
      Statement* as = Statement::make_assignment(eref, erhs, loc);

      as = gogo->check_write_barrier(context->block(), as, cs);
      Bstatement* s = as->get_backend(context);

      assn = gogo->backend()->compound_statement(edecl, s);
    }
  decl = gogo->backend()->compound_statement(decl, assn);
  space = gogo->backend()->var_expression(space_temp, loc);
  return gogo->backend()->compound_expression(decl, space, loc);
}

// Dump ast representation for a heap expression.

void
Heap_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "&(";
  ast_dump_context->dump_expression(this->expr_);
  ast_dump_context->ostream() << ")";
}

// Allocate an expression on the heap.

Expression*
Expression::make_heap_expression(Expression* expr, Location location)
{
  return new Heap_expression(expr, location);
}

// Class Receive_expression.

// Return the type of a receive expression.

Type*
Receive_expression::do_type()
{
  if (this->is_error_expression())
    return Type::make_error_type();
  Channel_type* channel_type = this->channel_->type()->channel_type();
  if (channel_type == NULL)
    {
      this->report_error(_("expected channel"));
      return Type::make_error_type();
    }
  return channel_type->element_type();
}

// Check types for a receive expression.

void
Receive_expression::do_check_types(Gogo*)
{
  Type* type = this->channel_->type();
  if (type->is_error())
    {
      go_assert(saw_errors());
      this->set_is_error();
      return;
    }
  if (type->channel_type() == NULL)
    {
      this->report_error(_("expected channel"));
      return;
    }
  if (!type->channel_type()->may_receive())
    {
      this->report_error(_("invalid receive on send-only channel"));
      return;
    }
}

// Flattening for receive expressions creates a temporary variable to store
// received data in for receives.

Expression*
Receive_expression::do_flatten(Gogo*, Named_object*,
                               Statement_inserter* inserter)
{
  Channel_type* channel_type = this->channel_->type()->channel_type();
  if (channel_type == NULL)
    {
      go_assert(saw_errors());
      return this;
    }
  else if (this->channel_->is_error_expression())
   {
     go_assert(saw_errors());
     return Expression::make_error(this->location());
   }

  Type* element_type = channel_type->element_type();
  if (this->temp_receiver_ == NULL)
    {
      this->temp_receiver_ = Statement::make_temporary(element_type, NULL,
						       this->location());
      this->temp_receiver_->set_is_address_taken();
      inserter->insert(this->temp_receiver_);
    }

  return this;
}

// Get the backend representation for a receive expression.

Bexpression*
Receive_expression::do_get_backend(Translate_context* context)
{
  Location loc = this->location();

  Channel_type* channel_type = this->channel_->type()->channel_type();
  if (channel_type == NULL)
    {
      go_assert(this->channel_->type()->is_error());
      return context->backend()->error_expression();
    }

  Expression* recv_ref =
    Expression::make_temporary_reference(this->temp_receiver_, loc);
  Expression* recv_addr =
    Expression::make_temporary_reference(this->temp_receiver_, loc);
  recv_addr = Expression::make_unary(OPERATOR_AND, recv_addr, loc);
  Expression* recv = Runtime::make_call(Runtime::CHANRECV1, loc, 2,
					this->channel_, recv_addr);
  return Expression::make_compound(recv, recv_ref, loc)->get_backend(context);
}

// Export a receive expression.

void
Receive_expression::do_export(Export_function_body* efb) const
{
  efb->write_c_string("<-");
  this->channel_->export_expression(efb);
}

// Dump ast representation for a receive expression.

void
Receive_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << " <- " ;
  ast_dump_context->dump_expression(channel_);
}

// Import a receive expression.

Expression*
Receive_expression::do_import(Import_expression* imp, Location loc)
{
  imp->require_c_string("<-");
  Expression* expr = Expression::import_expression(imp, loc);
  return Expression::make_receive(expr, loc);
}

// Make a receive expression.

Receive_expression*
Expression::make_receive(Expression* channel, Location location)
{
  return new Receive_expression(channel, location);
}

// An expression which evaluates to a pointer to the type descriptor
// of a type.

class Type_descriptor_expression : public Expression
{
 public:
  Type_descriptor_expression(Type* type, Location location)
    : Expression(EXPRESSION_TYPE_DESCRIPTOR, location),
      type_(type)
  { }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type()
  { return Type::make_type_descriptor_ptr_type(); }

  bool
  do_is_static_initializer() const
  { return true; }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context* context)
  {
    return this->type_->type_descriptor_pointer(context->gogo(),
						this->location());
  }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type for which this is the descriptor.
  Type* type_;
};

int
Type_descriptor_expression::do_traverse(Traverse* traverse)
{
  if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Dump ast representation for a type descriptor expression.

void
Type_descriptor_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->dump_type(this->type_);
}

// Make a type descriptor expression.

Expression*
Expression::make_type_descriptor(Type* type, Location location)
{
  return new Type_descriptor_expression(type, location);
}

// An expression which evaluates to a pointer to the Garbage Collection symbol
// of a type.

class GC_symbol_expression : public Expression
{
 public:
  GC_symbol_expression(Type* type)
    : Expression(EXPRESSION_GC_SYMBOL, Linemap::predeclared_location()),
      type_(type)
  {}

 protected:
  Type*
  do_type()
  { return Type::make_pointer_type(Type::lookup_integer_type("uint8")); }

  bool
  do_is_static_initializer() const
  { return true; }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context* context)
  { return this->type_->gc_symbol_pointer(context->gogo()); }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type which this gc symbol describes.
  Type* type_;
};

// Dump ast representation for a gc symbol expression.

void
GC_symbol_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "gcdata(";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << ")";
}

// Make a gc symbol expression.

Expression*
Expression::make_gc_symbol(Type* type)
{
  return new GC_symbol_expression(type);
}

// An expression that evaluates to a pointer to a symbol holding the
// ptrmask data of a type.

class Ptrmask_symbol_expression : public Expression
{
 public:
  Ptrmask_symbol_expression(Type* type)
    : Expression(EXPRESSION_PTRMASK_SYMBOL, Linemap::predeclared_location()),
      type_(type)
  {}

 protected:
  Type*
  do_type()
  { return Type::make_pointer_type(Type::lookup_integer_type("uint8")); }

  bool
  do_is_static_initializer() const
  { return true; }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type that this ptrmask symbol describes.
  Type* type_;
};

// Return the ptrmask variable.

Bexpression*
Ptrmask_symbol_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();

  // If this type does not need a gcprog, then we can use the standard
  // GC symbol.
  int64_t ptrsize, ptrdata;
  if (!this->type_->needs_gcprog(gogo, &ptrsize, &ptrdata))
    return this->type_->gc_symbol_pointer(gogo);

  // Otherwise we have to build a ptrmask variable, and return a
  // pointer to it.

  Bvariable* bvar = this->type_->gc_ptrmask_var(gogo, ptrsize, ptrdata);
  Location bloc = Linemap::predeclared_location();
  Bexpression* bref = gogo->backend()->var_expression(bvar, bloc);
  Bexpression* baddr = gogo->backend()->address_expression(bref, bloc);

  Type* uint8_type = Type::lookup_integer_type("uint8");
  Type* pointer_uint8_type = Type::make_pointer_type(uint8_type);
  Btype* ubtype = pointer_uint8_type->get_backend(gogo);
  return gogo->backend()->convert_expression(ubtype, baddr, bloc);
}

// Dump AST for a ptrmask symbol expression.

void
Ptrmask_symbol_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "ptrmask(";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << ")";
}

// Make a ptrmask symbol expression.

Expression*
Expression::make_ptrmask_symbol(Type* type)
{
  return new Ptrmask_symbol_expression(type);
}

// An expression which evaluates to some characteristic of a type.
// This is only used to initialize fields of a type descriptor.  Using
// a new expression class is slightly inefficient but gives us a good
// separation between the frontend and the middle-end with regard to
// how types are laid out.

class Type_info_expression : public Expression
{
 public:
  Type_info_expression(Type* type, Type_info type_info)
    : Expression(EXPRESSION_TYPE_INFO, Linemap::predeclared_location()),
      type_(type), type_info_(type_info)
  { }

 protected:
  bool
  do_is_static_initializer() const
  { return true; }

  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type for which we are getting information.
  Type* type_;
  // What information we want.
  Type_info type_info_;
};

// The type is chosen to match what the type descriptor struct
// expects.

Type*
Type_info_expression::do_type()
{
  switch (this->type_info_)
    {
    case TYPE_INFO_SIZE:
    case TYPE_INFO_BACKEND_PTRDATA:
    case TYPE_INFO_DESCRIPTOR_PTRDATA:
      return Type::lookup_integer_type("uintptr");
    case TYPE_INFO_ALIGNMENT:
    case TYPE_INFO_FIELD_ALIGNMENT:
      return Type::lookup_integer_type("uint8");
    default:
      go_unreachable();
    }
}

// Return the backend representation for type information.

Bexpression*
Type_info_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  bool ok = true;
  int64_t val;
  switch (this->type_info_)
    {
    case TYPE_INFO_SIZE:
      ok = this->type_->backend_type_size(gogo, &val);
      break;
    case TYPE_INFO_ALIGNMENT:
      ok = this->type_->backend_type_align(gogo, &val);
      break;
    case TYPE_INFO_FIELD_ALIGNMENT:
      ok = this->type_->backend_type_field_align(gogo, &val);
      break;
    case TYPE_INFO_BACKEND_PTRDATA:
      ok = this->type_->backend_type_ptrdata(gogo, &val);
      break;
    case TYPE_INFO_DESCRIPTOR_PTRDATA:
      ok = this->type_->descriptor_ptrdata(gogo, &val);
      break;
    default:
      go_unreachable();
    }
  if (!ok)
    {
      go_assert(saw_errors());
      return gogo->backend()->error_expression();
    }
  Expression* e = Expression::make_integer_int64(val, this->type(),
						 this->location());
  return e->get_backend(context);
}

// Dump ast representation for a type info expression.

void
Type_info_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "typeinfo(";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << ",";
  ast_dump_context->ostream() <<
    (this->type_info_ == TYPE_INFO_ALIGNMENT ? "alignment"
    : this->type_info_ == TYPE_INFO_FIELD_ALIGNMENT ? "field alignment"
    : this->type_info_ == TYPE_INFO_SIZE ? "size"
    : this->type_info_ == TYPE_INFO_BACKEND_PTRDATA ? "backend_ptrdata"
    : this->type_info_ == TYPE_INFO_DESCRIPTOR_PTRDATA ? "descriptor_ptrdata"
    : "unknown");
  ast_dump_context->ostream() << ")";
}

// Make a type info expression.

Expression*
Expression::make_type_info(Type* type, Type_info type_info)
{
  return new Type_info_expression(type, type_info);
}

// An expression that evaluates to some characteristic of a slice.
// This is used when indexing, bound-checking, or nil checking a slice.

class Slice_info_expression : public Expression
{
 public:
  Slice_info_expression(Expression* slice, Slice_info slice_info,
                        Location location)
    : Expression(EXPRESSION_SLICE_INFO, location),
      slice_(slice), slice_info_(slice_info)
  { }

 protected:
  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  {
    return new Slice_info_expression(this->slice_->copy(), this->slice_info_,
                                     this->location());
  }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

  void
  do_issue_nil_check()
  { this->slice_->issue_nil_check(); }

 private:
  // The slice for which we are getting information.
  Expression* slice_;
  // What information we want.
  Slice_info slice_info_;
};

// Return the type of the slice info.

Type*
Slice_info_expression::do_type()
{
  switch (this->slice_info_)
    {
    case SLICE_INFO_VALUE_POINTER:
      return Type::make_pointer_type(
          this->slice_->type()->array_type()->element_type());
    case SLICE_INFO_LENGTH:
    case SLICE_INFO_CAPACITY:
        return Type::lookup_integer_type("int");
    default:
      go_unreachable();
    }
}

// Return the backend information for slice information.

Bexpression*
Slice_info_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Bexpression* bslice = this->slice_->get_backend(context);
  switch (this->slice_info_)
    {
    case SLICE_INFO_VALUE_POINTER:
    case SLICE_INFO_LENGTH:
    case SLICE_INFO_CAPACITY:
      return gogo->backend()->struct_field_expression(bslice, this->slice_info_,
						      this->location());
      break;
    default:
      go_unreachable();
    }
}

// Dump ast representation for a type info expression.

void
Slice_info_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "sliceinfo(";
  this->slice_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ",";
  ast_dump_context->ostream() <<
      (this->slice_info_ == SLICE_INFO_VALUE_POINTER ? "values"
    : this->slice_info_ == SLICE_INFO_LENGTH ? "length"
    : this->slice_info_ == SLICE_INFO_CAPACITY ? "capacity "
    : "unknown");
  ast_dump_context->ostream() << ")";
}

// Make a slice info expression.

Expression*
Expression::make_slice_info(Expression* slice, Slice_info slice_info,
                            Location location)
{
  return new Slice_info_expression(slice, slice_info, location);
}

// Class Slice_value_expression.

int
Slice_value_expression::do_traverse(Traverse* traverse)
{
  if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->valmem_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->len_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

Expression*
Slice_value_expression::do_copy()
{
  return new Slice_value_expression(this->type_->copy_expressions(),
				    this->valmem_->copy(),
				    this->len_->copy(), this->cap_->copy(),
				    this->location());
}

Bexpression*
Slice_value_expression::do_get_backend(Translate_context* context)
{
  std::vector<Bexpression*> vals(3);
  vals[0] = this->valmem_->get_backend(context);
  vals[1] = this->len_->get_backend(context);
  vals[2] = this->cap_->get_backend(context);

  Gogo* gogo = context->gogo();
  Btype* btype = this->type_->get_backend(gogo);
  return gogo->backend()->constructor_expression(btype, vals, this->location());
}

void
Slice_value_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "slicevalue(";
  ast_dump_context->ostream() << "values: ";
  this->valmem_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ", length: ";
  this->len_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ", capacity: ";
  this->cap_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ")";
}

Expression*
Expression::make_slice_value(Type* at, Expression* valmem, Expression* len,
                             Expression* cap, Location location)
{
  go_assert(at->is_slice_type());
  go_assert(valmem->is_nil_expression()
	    || (at->array_type()->element_type()
		== valmem->type()->points_to()));
  return new Slice_value_expression(at, valmem, len, cap, location);
}

// Look through the expression of a Slice_value_expression's valmem to
// find an call to makeslice.  If found, return the call expression and
// the containing temporary statement (if any).

std::pair<Call_expression*, Temporary_statement*>
Expression::find_makeslice_call(Expression* expr)
{
  Unsafe_type_conversion_expression* utce =
    expr->unsafe_conversion_expression();
  if (utce != NULL)
    expr = utce->expr();

  Slice_value_expression* sve = expr->slice_value_expression();
  if (sve == NULL)
    return std::make_pair<Call_expression*, Temporary_statement*>(NULL, NULL);
  expr = sve->valmem();

  utce = expr->unsafe_conversion_expression();
  if (utce != NULL)
    expr = utce->expr();

  Temporary_reference_expression* tre = expr->temporary_reference_expression();
  Temporary_statement* ts = (tre != NULL ? tre->statement() : NULL);
  if (ts != NULL && ts->init() != NULL && !ts->assigned()
      && !ts->is_address_taken())
    expr = ts->init();

  Call_expression* call = expr->call_expression();
  if (call == NULL)
    return std::make_pair<Call_expression*, Temporary_statement*>(NULL, NULL);

  Func_expression* fe = call->fn()->func_expression();
  if (fe != NULL
      && fe->runtime_code() == Runtime::MAKESLICE)
    return std::make_pair(call, ts);

  return std::make_pair<Call_expression*, Temporary_statement*>(NULL, NULL);
}

// An expression that evaluates to some characteristic of a non-empty interface.
// This is used to access the method table or underlying object of an interface.

class Interface_info_expression : public Expression
{
 public:
  Interface_info_expression(Expression* iface, Interface_info iface_info,
                            Location location)
    : Expression(EXPRESSION_INTERFACE_INFO, location),
      iface_(iface), iface_info_(iface_info)
  { }

 protected:
  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  {
    return new Interface_info_expression(this->iface_->copy(),
                                         this->iface_info_, this->location());
  }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

  void
  do_issue_nil_check()
  { this->iface_->issue_nil_check(); }

 private:
  // The interface for which we are getting information.
  Expression* iface_;
  // What information we want.
  Interface_info iface_info_;
};

// Return the type of the interface info.

Type*
Interface_info_expression::do_type()
{
  switch (this->iface_info_)
    {
    case INTERFACE_INFO_METHODS:
      {
        typedef Unordered_map(Interface_type*, Type*) Hashtable;
        static Hashtable result_types;

        Interface_type* itype = this->iface_->type()->interface_type();

        Hashtable::const_iterator pr = result_types.find(itype);
        if (pr != result_types.end())
          return pr->second;

        Type* pdt = Type::make_type_descriptor_ptr_type();
        if (itype->is_empty())
          {
            result_types[itype] = pdt;
            return pdt;
          }

        Location loc = this->location();
        Struct_field_list* sfl = new Struct_field_list();
        sfl->push_back(
            Struct_field(Typed_identifier("__type_descriptor", pdt, loc)));

        for (Typed_identifier_list::const_iterator p = itype->methods()->begin();
             p != itype->methods()->end();
             ++p)
          {
            Function_type* ft = p->type()->function_type();
            go_assert(ft->receiver() == NULL);

            const Typed_identifier_list* params = ft->parameters();
            Typed_identifier_list* mparams = new Typed_identifier_list();
            if (params != NULL)
              mparams->reserve(params->size() + 1);
            Type* vt = Type::make_pointer_type(Type::make_void_type());
            mparams->push_back(Typed_identifier("", vt, ft->location()));
            if (params != NULL)
              {
                for (Typed_identifier_list::const_iterator pp = params->begin();
                     pp != params->end();
                     ++pp)
                  mparams->push_back(*pp);
              }

            Typed_identifier_list* mresults = (ft->results() == NULL
                                               ? NULL
                                               : ft->results()->copy());
            Backend_function_type* mft =
                Type::make_backend_function_type(NULL, mparams, mresults,
                                                 ft->location());

            std::string fname = Gogo::unpack_hidden_name(p->name());
            sfl->push_back(Struct_field(Typed_identifier(fname, mft, loc)));
          }

	Struct_type* st = Type::make_struct_type(sfl, loc);
	st->set_is_struct_incomparable();
	Pointer_type *pt = Type::make_pointer_type(st);
        result_types[itype] = pt;
        return pt;
      }
    case INTERFACE_INFO_OBJECT:
      return Type::make_pointer_type(Type::make_void_type());
    default:
      go_unreachable();
    }
}

// Return the backend representation for interface information.

Bexpression*
Interface_info_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Bexpression* biface = this->iface_->get_backend(context);
  switch (this->iface_info_)
    {
    case INTERFACE_INFO_METHODS:
    case INTERFACE_INFO_OBJECT:
      return gogo->backend()->struct_field_expression(biface, this->iface_info_,
						      this->location());
      break;
    default:
      go_unreachable();
    }
}

// Dump ast representation for an interface info expression.

void
Interface_info_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  bool is_empty = this->iface_->type()->interface_type()->is_empty();
  ast_dump_context->ostream() << "interfaceinfo(";
  this->iface_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ",";
  ast_dump_context->ostream() <<
      (this->iface_info_ == INTERFACE_INFO_METHODS && !is_empty ? "methods"
    : this->iface_info_ == INTERFACE_INFO_TYPE_DESCRIPTOR ? "type_descriptor"
    : this->iface_info_ == INTERFACE_INFO_OBJECT ? "object"
    : "unknown");
  ast_dump_context->ostream() << ")";
}

// Make an interface info expression.

Expression*
Expression::make_interface_info(Expression* iface, Interface_info iface_info,
                                Location location)
{
  return new Interface_info_expression(iface, iface_info, location);
}

// An expression that represents an interface value.  The first field is either
// a type descriptor for an empty interface or a pointer to the interface method
// table for a non-empty interface.  The second field is always the object.

class Interface_value_expression : public Expression
{
 public:
  Interface_value_expression(Type* type, Expression* first_field,
                             Expression* obj, Location location)
      : Expression(EXPRESSION_INTERFACE_VALUE, location),
        type_(type), first_field_(first_field), obj_(obj)
  { }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*)
  { go_unreachable(); }

  Expression*
  do_copy()
  {
    return new Interface_value_expression(this->type_->copy_expressions(),
                                          this->first_field_->copy(),
                                          this->obj_->copy(), this->location());
  }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type of the interface value.
  Type* type_;
  // The first field of the interface (either a type descriptor or a pointer
  // to the method table.
  Expression* first_field_;
  // The underlying object of the interface.
  Expression* obj_;
};

int
Interface_value_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->first_field_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->obj_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

Bexpression*
Interface_value_expression::do_get_backend(Translate_context* context)
{
  std::vector<Bexpression*> vals(2);
  vals[0] = this->first_field_->get_backend(context);
  vals[1] = this->obj_->get_backend(context);

  Gogo* gogo = context->gogo();
  Btype* btype = this->type_->get_backend(gogo);
  return gogo->backend()->constructor_expression(btype, vals, this->location());
}

void
Interface_value_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "interfacevalue(";
  ast_dump_context->ostream() <<
      (this->type_->interface_type()->is_empty()
       ? "type_descriptor: "
       : "methods: ");
  this->first_field_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ", object: ";
  this->obj_->dump_expression(ast_dump_context);
  ast_dump_context->ostream() << ")";
}

Expression*
Expression::make_interface_value(Type* type, Expression* first_value,
                                 Expression* object, Location location)
{
  return new Interface_value_expression(type, first_value, object, location);
}

// An interface method table for a pair of types: an interface type and a type
// that implements that interface.

class Interface_mtable_expression : public Expression
{
 public:
  Interface_mtable_expression(Interface_type* itype, Type* type,
                              bool is_pointer, Location location)
      : Expression(EXPRESSION_INTERFACE_MTABLE, location),
        itype_(itype), type_(type), is_pointer_(is_pointer),
	method_table_type_(NULL), bvar_(NULL)
  { }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type();

  bool
  do_is_static_initializer() const
  { return true; }

  void
  do_determine_type(const Type_context*)
  { go_unreachable(); }

  Expression*
  do_copy()
  {
    Interface_type* itype = this->itype_->copy_expressions()->interface_type();
    return new Interface_mtable_expression(itype,
					   this->type_->copy_expressions(),
                                           this->is_pointer_, this->location());
  }

  bool
  do_is_addressable() const
  { return true; }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The interface type for which the methods are defined.
  Interface_type* itype_;
  // The type to construct the interface method table for.
  Type* type_;
  // Whether this table contains the method set for the receiver type or the
  // pointer receiver type.
  bool is_pointer_;
  // The type of the method table.
  Type* method_table_type_;
  // The backend variable that refers to the interface method table.
  Bvariable* bvar_;
};

int
Interface_mtable_expression::do_traverse(Traverse* traverse)
{
  if (Type::traverse(this->itype_, traverse) == TRAVERSE_EXIT
      || Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

Type*
Interface_mtable_expression::do_type()
{
  if (this->method_table_type_ != NULL)
    return this->method_table_type_;

  const Typed_identifier_list* interface_methods = this->itype_->methods();
  go_assert(!interface_methods->empty());

  Struct_field_list* sfl = new Struct_field_list;
  Typed_identifier tid("__type_descriptor", Type::make_type_descriptor_ptr_type(),
                       this->location());
  sfl->push_back(Struct_field(tid));
  Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
  for (Typed_identifier_list::const_iterator p = interface_methods->begin();
       p != interface_methods->end();
       ++p)
    {
      // We want C function pointers here, not func descriptors; model
      // using void* pointers.
      Typed_identifier method(p->name(), unsafe_ptr_type, p->location());
      sfl->push_back(Struct_field(method));
    }
  Struct_type* st = Type::make_struct_type(sfl, this->location());
  st->set_is_struct_incomparable();
  this->method_table_type_ = st;
  return this->method_table_type_;
}

Bexpression*
Interface_mtable_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Location loc = Linemap::predeclared_location();
  if (this->bvar_ != NULL)
    return gogo->backend()->var_expression(this->bvar_, this->location());

  const Typed_identifier_list* interface_methods = this->itype_->methods();
  go_assert(!interface_methods->empty());

  std::string mangled_name =
    gogo->interface_method_table_name(this->itype_, this->type_,
				      this->is_pointer_);

  // Set is_public if we are converting a named type to an interface
  // type that is defined in the same package as the named type, and
  // the interface has hidden methods.  In that case the interface
  // method table will be defined by the package that defines the
  // types.
  bool is_public = false;
  if (this->type_->named_type() != NULL
      && (this->type_->named_type()->named_object()->package()
	  == this->itype_->package()))
    {
      for (Typed_identifier_list::const_iterator p = interface_methods->begin();
	   p != interface_methods->end();
	   ++p)
	{
	  if (Gogo::is_hidden_name(p->name()))
	    {
	      is_public = true;
	      break;
	    }
	}
    }

  if (is_public
      && this->type_->named_type()->named_object()->package() != NULL)
    {
      // The interface conversion table is defined elsewhere.
      Btype* btype = this->type()->get_backend(gogo);
      this->bvar_ =
          gogo->backend()->immutable_struct_reference(mangled_name, "",
                                                      btype, loc);
      return gogo->backend()->var_expression(this->bvar_, this->location());
    }

  // The first element is the type descriptor.
  Type* td_type;
  if (!this->is_pointer_)
    td_type = this->type_;
  else
    td_type = Type::make_pointer_type(this->type_);

  std::vector<Backend::Btyped_identifier> bstructfields;

  // Build an interface method table for a type: a type descriptor followed by a
  // list of function pointers, one for each interface method.  This is used for
  // interfaces.
  Expression_list* svals = new Expression_list();
  Expression* tdescriptor = Expression::make_type_descriptor(td_type, loc);
  svals->push_back(tdescriptor);

  Btype* tdesc_btype = tdescriptor->type()->get_backend(gogo);
  Backend::Btyped_identifier btd("_type", tdesc_btype, loc);
  bstructfields.push_back(btd);

  Named_type* nt = this->type_->named_type();
  Struct_type* st = this->type_->struct_type();
  go_assert(nt != NULL || st != NULL);

  for (Typed_identifier_list::const_iterator p = interface_methods->begin();
       p != interface_methods->end();
       ++p)
    {
      bool is_ambiguous;
      Method* m;
      if (nt != NULL)
	m = nt->method_function(p->name(), &is_ambiguous);
      else
	m = st->method_function(p->name(), &is_ambiguous);
      go_assert(m != NULL);
      Named_object* no =
        (this->is_pointer_
         && this->type_->is_direct_iface_type()
         && m->is_value_method()
         ? m->iface_stub_object()
         : m->named_object());

      go_assert(no->is_function() || no->is_function_declaration());

      Function_type* fcn_type = (no->is_function()
                                 ? no->func_value()->type()
                                 : no->func_declaration_value()->type());
      Btype* fcn_btype = fcn_type->get_backend_fntype(gogo);
      Backend::Btyped_identifier bmtype(p->name(), fcn_btype, loc);
      bstructfields.push_back(bmtype);

      svals->push_back(Expression::make_func_code_reference(no, loc));
    }

  Btype *btype = gogo->backend()->struct_type(bstructfields);
  std::vector<Bexpression*> ctor_bexprs;
  for (Expression_list::const_iterator pe = svals->begin();
       pe != svals->end();
       ++pe)
    {
      ctor_bexprs.push_back((*pe)->get_backend(context));
    }
  Bexpression* ctor =
      gogo->backend()->constructor_expression(btype, ctor_bexprs, loc);

  unsigned int flags = 0;
  if (!is_public)
    flags |= Backend::variable_is_hidden;
  this->bvar_ = gogo->backend()->immutable_struct(mangled_name, "", flags,
						  btype, loc);
  gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, flags,
					     btype, loc, ctor);
  return gogo->backend()->var_expression(this->bvar_, loc);
}

void
Interface_mtable_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "__go_"
                              << (this->is_pointer_ ? "pimt__" : "imt_");
  ast_dump_context->dump_type(this->itype_);
  ast_dump_context->ostream() << "__";
  ast_dump_context->dump_type(this->type_);
}

Expression*
Expression::make_interface_mtable_ref(Interface_type* itype, Type* type,
                                      bool is_pointer, Location location)
{
  return new Interface_mtable_expression(itype, type, is_pointer, location);
}

// An expression which evaluates to the offset of a field within a
// struct.  This, like Type_info_expression, q.v., is only used to
// initialize fields of a type descriptor.

class Struct_field_offset_expression : public Expression
{
 public:
  Struct_field_offset_expression(Struct_type* type, const Struct_field* field)
    : Expression(EXPRESSION_STRUCT_FIELD_OFFSET,
		 Linemap::predeclared_location()),
      type_(type), field_(field)
  { }

 protected:
  bool
  do_is_static_initializer() const
  { return true; }

  Type*
  do_type()
  { return Type::lookup_integer_type("uintptr"); }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type of the struct.
  Struct_type* type_;
  // The field.
  const Struct_field* field_;
};

// Return the backend representation for a struct field offset.

Bexpression*
Struct_field_offset_expression::do_get_backend(Translate_context* context)
{
  const Struct_field_list* fields = this->type_->fields();
  Struct_field_list::const_iterator p;
  unsigned i = 0;
  for (p = fields->begin();
       p != fields->end();
       ++p, ++i)
    if (&*p == this->field_)
      break;
  go_assert(&*p == this->field_);

  Gogo* gogo = context->gogo();
  Btype* btype = this->type_->get_backend(gogo);

  int64_t offset = gogo->backend()->type_field_offset(btype, i);
  Type* uptr_type = Type::lookup_integer_type("uintptr");
  Expression* ret =
    Expression::make_integer_int64(offset, uptr_type,
				   Linemap::predeclared_location());
  return ret->get_backend(context);
}

// Dump ast representation for a struct field offset expression.

void
Struct_field_offset_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() <<  "unsafe.Offsetof(";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << '.';
  ast_dump_context->ostream() <<
    Gogo::message_name(this->field_->field_name());
  ast_dump_context->ostream() << ")";
}

// Make an expression for a struct field offset.

Expression*
Expression::make_struct_field_offset(Struct_type* type,
				     const Struct_field* field)
{
  return new Struct_field_offset_expression(type, field);
}

// An expression which evaluates to the address of an unnamed label.

class Label_addr_expression : public Expression
{
 public:
  Label_addr_expression(Label* label, Location location)
    : Expression(EXPRESSION_LABEL_ADDR, location),
      label_(label)
  { }

 protected:
  Type*
  do_type()
  { return Type::make_pointer_type(Type::make_void_type()); }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return new Label_addr_expression(this->label_, this->location()); }

  Bexpression*
  do_get_backend(Translate_context* context)
  { return this->label_->get_addr(context, this->location()); }

  void
  do_dump_expression(Ast_dump_context* ast_dump_context) const
  { ast_dump_context->ostream() << this->label_->name(); }

 private:
  // The label whose address we are taking.
  Label* label_;
};

// Make an expression for the address of an unnamed label.

Expression*
Expression::make_label_addr(Label* label, Location location)
{
  return new Label_addr_expression(label, location);
}

// Class Conditional_expression.

// Traversal.

int
Conditional_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->cond_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->then_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->else_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Return the type of the conditional expression.

Type*
Conditional_expression::do_type()
{
  Type* result_type = Type::make_void_type();
  if (Type::are_identical(this->then_->type(), this->else_->type(),
			  Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
                          NULL))
    result_type = this->then_->type();
  else if (this->then_->is_nil_expression()
           || this->else_->is_nil_expression())
    result_type = (!this->then_->is_nil_expression()
                   ? this->then_->type()
                   : this->else_->type());
  return result_type;
}

// Determine type for a conditional expression.

void
Conditional_expression::do_determine_type(const Type_context* context)
{
  this->cond_->determine_type_no_context();
  this->then_->determine_type(context);
  this->else_->determine_type(context);
}

// Get the backend representation of a conditional expression.

Bexpression*
Conditional_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Btype* result_btype = this->type()->get_backend(gogo);
  Bexpression* cond = this->cond_->get_backend(context);
  Bexpression* then = this->then_->get_backend(context);
  Bexpression* belse = this->else_->get_backend(context);
  Bfunction* bfn = context->function()->func_value()->get_decl();
  return gogo->backend()->conditional_expression(bfn, result_btype, cond, then,
						 belse, this->location());
}

// Dump ast representation of a conditional expression.

void
Conditional_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "(";
  ast_dump_context->dump_expression(this->cond_);
  ast_dump_context->ostream() << " ? ";
  ast_dump_context->dump_expression(this->then_);
  ast_dump_context->ostream() << " : ";
  ast_dump_context->dump_expression(this->else_);
  ast_dump_context->ostream() << ") ";
}

// Make a conditional expression.

Expression*
Expression::make_conditional(Expression* cond, Expression* then,
                             Expression* else_expr, Location location)
{
  return new Conditional_expression(cond, then, else_expr, location);
}

// Class Compound_expression.

// Traversal.

int
Compound_expression::do_traverse(Traverse* traverse)
{
  if (Expression::traverse(&this->init_, traverse) == TRAVERSE_EXIT
      || Expression::traverse(&this->expr_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return TRAVERSE_CONTINUE;
}

// Return the type of the compound expression.

Type*
Compound_expression::do_type()
{
  return this->expr_->type();
}

// Determine type for a compound expression.

void
Compound_expression::do_determine_type(const Type_context* context)
{
  this->init_->determine_type_no_context();
  this->expr_->determine_type(context);
}

// Get the backend representation of a compound expression.

Bexpression*
Compound_expression::do_get_backend(Translate_context* context)
{
  Gogo* gogo = context->gogo();
  Bexpression* binit = this->init_->get_backend(context);
  Bfunction* bfunction = context->function()->func_value()->get_decl();
  Bstatement* init_stmt = gogo->backend()->expression_statement(bfunction,
                                                                binit);
  Bexpression* bexpr = this->expr_->get_backend(context);
  return gogo->backend()->compound_expression(init_stmt, bexpr,
					      this->location());
}

// Dump ast representation of a conditional expression.

void
Compound_expression::do_dump_expression(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "(";
  ast_dump_context->dump_expression(this->init_);
  ast_dump_context->ostream() << ",";
  ast_dump_context->dump_expression(this->expr_);
  ast_dump_context->ostream() << ") ";
}

// Make a compound expression.

Expression*
Expression::make_compound(Expression* init, Expression* expr, Location location)
{
  return new Compound_expression(init, expr, location);
}

// Class Backend_expression.

int
Backend_expression::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

Expression*
Backend_expression::do_copy()
{
  return new Backend_expression(this->bexpr_, this->type_->copy_expressions(),
				this->location());
}

void
Backend_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->ostream() << "backend_expression<";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream() << ">";
}

Expression*
Expression::make_backend(Bexpression* bexpr, Type* type, Location location)
{
  return new Backend_expression(bexpr, type, location);
}

// Import an expression.  This comes at the end in order to see the
// various class definitions.

Expression*
Expression::import_expression(Import_expression* imp, Location loc)
{
  Expression* expr = Expression::import_expression_without_suffix(imp, loc);
  while (true)
    {
      if (imp->match_c_string("("))
	{
	  imp->advance(1);
	  Expression_list* args = new Expression_list();
	  bool is_varargs = false;
	  while (!imp->match_c_string(")"))
	    {
	      Expression* arg = Expression::import_expression(imp, loc);
	      if (arg->is_error_expression())
		return arg;
	      args->push_back(arg);
	      if (imp->match_c_string(")"))
		break;
	      else if (imp->match_c_string("...)"))
		{
		  imp->advance(3);
		  is_varargs = true;
		  break;
		}
	      imp->require_c_string(", ");
	    }
	  imp->require_c_string(")");
	  expr = Expression::make_call(expr, args, is_varargs, loc);
          expr->call_expression()->set_varargs_are_lowered();
	}
      else if (imp->match_c_string("["))
	{
	  imp->advance(1);
	  Expression* start = Expression::import_expression(imp, loc);
	  Expression* end = NULL;
	  Expression* cap = NULL;
	  if (imp->match_c_string(":"))
	    {
	      imp->advance(1);
	      int c = imp->peek_char();
	      if (c == ':' || c == ']')
		end = Expression::make_nil(loc);
	      else
		end = Expression::import_expression(imp, loc);
	      if (imp->match_c_string(":"))
		{
		  imp->advance(1);
		  cap = Expression::import_expression(imp, loc);
		}
	    }
	  imp->require_c_string("]");
	  expr = Expression::make_index(expr, start, end, cap, loc);
	}
      else
	break;
    }

  return expr;
}

// Import an expression without considering a suffix (function
// arguments, index operations, etc.).

Expression*
Expression::import_expression_without_suffix(Import_expression* imp,
					     Location loc)
{
  int c = imp->peek_char();
  if (c == '+' || c == '-' || c == '!' || c == '^' || c == '&' || c == '*')
    return Unary_expression::do_import(imp, loc);
  else if (c == '(')
    return Binary_expression::do_import(imp, loc);
  else if (imp->match_c_string("$true")
	   || imp->match_c_string("$false")
	   || (imp->version() < EXPORT_FORMAT_V3
	       && (imp->match_c_string("true")
		   || imp->match_c_string("false"))))
    return Boolean_expression::do_import(imp, loc);
  else if (c == '"')
    return String_expression::do_import(imp, loc);
  else if (c == '-' || (c >= '0' && c <= '9'))
    {
      // This handles integers, floats and complex constants.
      return Integer_expression::do_import(imp, loc);
    }
  else if (imp->match_c_string("<-"))
    return Receive_expression::do_import(imp, loc);
  else if (imp->match_c_string("$nil")
	   || (imp->version() < EXPORT_FORMAT_V3
	       && imp->match_c_string("nil")))
    return Nil_expression::do_import(imp, loc);
  else if (imp->match_c_string("$convert")
	   || (imp->version() < EXPORT_FORMAT_V3
	       && imp->match_c_string("convert")))
    return Type_conversion_expression::do_import(imp, loc);

  Import_function_body* ifb = imp->ifb();
  if (ifb == NULL)
    {
      go_error_at(imp->location(), "import error: expected expression");
      return Expression::make_error(loc);
    }
  if (ifb->saw_error())
    return Expression::make_error(loc);

  if (ifb->match_c_string("$t"))
    return Temporary_reference_expression::do_import(ifb, loc);

  return Expression::import_identifier(ifb, loc);
}

// Import an identifier in an expression.  This is a reference to a
// variable or function.

Expression*
Expression::import_identifier(Import_function_body* ifb, Location loc)
{
  std::string id;
  Package* pkg;
  bool is_exported;
  if (!Import::read_qualified_identifier(ifb, &id, &pkg, &is_exported))
    {
      if (!ifb->saw_error())
	go_error_at(ifb->location(),
		    "import error for %qs: bad qualified identifier at %lu",
		    ifb->name().c_str(),
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return Expression::make_error(loc);
    }

  Named_object* no = NULL;
  if (pkg == NULL && is_exported)
    no = ifb->block()->bindings()->lookup(id);
  if (no == NULL)
    {
      const Package* ipkg = pkg;
      if (ipkg == NULL)
	ipkg = ifb->function()->package();
      if (!is_exported)
	id = '.' + ipkg->pkgpath() + '.' + id;
      no = ipkg->bindings()->lookup(id);
    }
  if (no == NULL)
    no = ifb->gogo()->lookup_global(id.c_str());

  if (no == NULL)
    {
      if (!ifb->saw_error())
	go_error_at(ifb->location(),
		    "import error for %qs: lookup of %qs failed",
		    ifb->name().c_str(), id.c_str());
      ifb->set_saw_error();
      return Expression::make_error(loc);
    }

  if (no->is_variable() || no->is_result_variable())
    return Expression::make_var_reference(no, loc);
  else if (no->is_function() || no->is_function_declaration())
    return Expression::make_func_reference(no, NULL, loc);
  else
    {
      if (!ifb->saw_error())
	go_error_at(ifb->location(),
		    ("import error for %qs: "
		     "unexpected type of identifier %qs (%d)"),
		    ifb->name().c_str(),
		    id.c_str(), no->classification());
      ifb->set_saw_error();
      return Expression::make_error(loc);
    }
}

// Class Expression_list.

// Traverse the list.

int
Expression_list::traverse(Traverse* traverse)
{
  for (Expression_list::iterator p = this->begin();
       p != this->end();
       ++p)
    {
      if (*p != NULL)
	{
	  if (Expression::traverse(&*p, traverse) == TRAVERSE_EXIT)
	    return TRAVERSE_EXIT;
	}
    }
  return TRAVERSE_CONTINUE;
}

// Copy the list.

Expression_list*
Expression_list::copy()
{
  Expression_list* ret = new Expression_list();
  for (Expression_list::iterator p = this->begin();
       p != this->end();
       ++p)
    {
      if (*p == NULL)
	ret->push_back(NULL);
      else
	ret->push_back((*p)->copy());
    }
  return ret;
}

// Return whether an expression list has an error expression.

bool
Expression_list::contains_error() const
{
  for (Expression_list::const_iterator p = this->begin();
       p != this->end();
       ++p)
    if (*p != NULL && (*p)->is_error_expression())
      return true;
  return false;
}

// Class Numeric_constant.

// Destructor.

Numeric_constant::~Numeric_constant()
{
  this->clear();
}

// Copy constructor.

Numeric_constant::Numeric_constant(const Numeric_constant& a)
  : classification_(a.classification_), type_(a.type_)
{
  switch (a.classification_)
    {
    case NC_INVALID:
      break;
    case NC_INT:
    case NC_RUNE:
      mpz_init_set(this->u_.int_val, a.u_.int_val);
      break;
    case NC_FLOAT:
      mpfr_init_set(this->u_.float_val, a.u_.float_val, MPFR_RNDN);
      break;
    case NC_COMPLEX:
      mpc_init2(this->u_.complex_val, mpc_precision);
      mpc_set(this->u_.complex_val, a.u_.complex_val, MPC_RNDNN);
      break;
    default:
      go_unreachable();
    }
}

// Assignment operator.

Numeric_constant&
Numeric_constant::operator=(const Numeric_constant& a)
{
  this->clear();
  this->classification_ = a.classification_;
  this->type_ = a.type_;
  switch (a.classification_)
    {
    case NC_INVALID:
      break;
    case NC_INT:
    case NC_RUNE:
      mpz_init_set(this->u_.int_val, a.u_.int_val);
      break;
    case NC_FLOAT:
      mpfr_init_set(this->u_.float_val, a.u_.float_val, MPFR_RNDN);
      break;
    case NC_COMPLEX:
      mpc_init2(this->u_.complex_val, mpc_precision);
      mpc_set(this->u_.complex_val, a.u_.complex_val, MPC_RNDNN);
      break;
    default:
      go_unreachable();
    }
  return *this;
}

// Check equality with another numeric constant.

bool
Numeric_constant::equals(const Numeric_constant& a) const
{
  if (this->classification_ != a.classification_)
    return false;

  if (this->type_ != NULL && a.type_ != NULL
      && !Type::are_identical(this->type_, a.type_,
			      Type::COMPARE_ALIASES, NULL))
    return false;

  switch (a.classification_)
    {
    case NC_INVALID:
      break;
    case NC_INT:
    case NC_RUNE:
      return mpz_cmp(this->u_.int_val, a.u_.int_val) == 0;
    case NC_FLOAT:
      return mpfr_cmp(this->u_.float_val, a.u_.float_val) == 0;
    case NC_COMPLEX:
      return mpc_cmp(this->u_.complex_val, a.u_.complex_val) == 0;
    default:
      go_unreachable();
    }
  return false;
}

// Clear the contents.

void
Numeric_constant::clear()
{
  switch (this->classification_)
    {
    case NC_INVALID:
      break;
    case NC_INT:
    case NC_RUNE:
      mpz_clear(this->u_.int_val);
      break;
    case NC_FLOAT:
      mpfr_clear(this->u_.float_val);
      break;
    case NC_COMPLEX:
      mpc_clear(this->u_.complex_val);
      break;
    default:
      go_unreachable();
    }
  this->classification_ = NC_INVALID;
}

// Set to an unsigned long value.

void
Numeric_constant::set_unsigned_long(Type* type, unsigned long val)
{
  this->clear();
  this->classification_ = NC_INT;
  this->type_ = type;
  mpz_init_set_ui(this->u_.int_val, val);
}

// Set to an integer value.

void
Numeric_constant::set_int(Type* type, const mpz_t val)
{
  this->clear();
  this->classification_ = NC_INT;
  this->type_ = type;
  mpz_init_set(this->u_.int_val, val);
}

// Set to a rune value.

void
Numeric_constant::set_rune(Type* type, const mpz_t val)
{
  this->clear();
  this->classification_ = NC_RUNE;
  this->type_ = type;
  mpz_init_set(this->u_.int_val, val);
}

// Set to a floating point value.

void
Numeric_constant::set_float(Type* type, const mpfr_t val)
{
  this->clear();
  this->classification_ = NC_FLOAT;
  this->type_ = type;

  // Numeric constants do not have negative zero values, so remove
  // them here.  They also don't have infinity or NaN values, but we
  // should never see them here.
  int bits = 0;
  if (type != NULL
      && type->float_type() != NULL
      && !type->float_type()->is_abstract())
    bits = type->float_type()->bits();
  if (Numeric_constant::is_float_neg_zero(val, bits))
    mpfr_init_set_ui(this->u_.float_val, 0, MPFR_RNDN);
  else
    mpfr_init_set(this->u_.float_val, val, MPFR_RNDN);
}

// Set to a complex value.

void
Numeric_constant::set_complex(Type* type, const mpc_t val)
{
  this->clear();
  this->classification_ = NC_COMPLEX;
  this->type_ = type;

  // Avoid negative zero as in set_float.
  int bits = 0;
  if (type != NULL
      && type->complex_type() != NULL
      && !type->complex_type()->is_abstract())
    bits = type->complex_type()->bits() / 2;

  mpfr_t real;
  mpfr_init_set(real, mpc_realref(val), MPFR_RNDN);
  if (Numeric_constant::is_float_neg_zero(real, bits))
    mpfr_set_ui(real, 0, MPFR_RNDN);

  mpfr_t imag;
  mpfr_init_set(imag, mpc_imagref(val), MPFR_RNDN);
  if (Numeric_constant::is_float_neg_zero(imag, bits))
    mpfr_set_ui(imag, 0, MPFR_RNDN);

  mpc_init2(this->u_.complex_val, mpc_precision);
  mpc_set_fr_fr(this->u_.complex_val, real, imag, MPC_RNDNN);

  mpfr_clear(real);
  mpfr_clear(imag);
}

// Return whether VAL, at a precision of BITS, is a negative zero.
// BITS may be zero in which case it is ignored.

bool
Numeric_constant::is_float_neg_zero(const mpfr_t val, int bits)
{
  if (!mpfr_signbit(val))
    return false;
  if (mpfr_zero_p(val))
    return true;
  mpfr_exp_t min_exp;
  switch (bits)
    {
    case 0:
      return false;
    case 32:
      // In a denormalized float32 the exponent is -126, and there are
      // 24 bits of which at least the last must be 1, so the smallest
      // representable non-zero exponent is -126 - (24 - 1) == -149.
      min_exp = -149;
      break;
    case 64:
      // Minimum exponent is -1022, there are 53 bits.
      min_exp = -1074;
      break;
    default:
      go_unreachable();
    }
  return mpfr_get_exp(val) < min_exp;
}

// Get an int value.

void
Numeric_constant::get_int(mpz_t* val) const
{
  go_assert(this->is_int());
  mpz_init_set(*val, this->u_.int_val);
}

// Get a rune value.

void
Numeric_constant::get_rune(mpz_t* val) const
{
  go_assert(this->is_rune());
  mpz_init_set(*val, this->u_.int_val);
}

// Get a floating point value.

void
Numeric_constant::get_float(mpfr_t* val) const
{
  go_assert(this->is_float());
  mpfr_init_set(*val, this->u_.float_val, MPFR_RNDN);
}

// Get a complex value.

void
Numeric_constant::get_complex(mpc_t* val) const
{
  go_assert(this->is_complex());
  mpc_init2(*val, mpc_precision);
  mpc_set(*val, this->u_.complex_val, MPC_RNDNN);
}

// Express value as unsigned long if possible.

Numeric_constant::To_unsigned_long
Numeric_constant::to_unsigned_long(unsigned long* val) const
{
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      return this->mpz_to_unsigned_long(this->u_.int_val, val);
    case NC_FLOAT:
      return this->mpfr_to_unsigned_long(this->u_.float_val, val);
    case NC_COMPLEX:
      if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
	return NC_UL_NOTINT;
      return this->mpfr_to_unsigned_long(mpc_realref(this->u_.complex_val),
					 val);
    default:
      go_unreachable();
    }
}

// Express integer value as unsigned long if possible.

Numeric_constant::To_unsigned_long
Numeric_constant::mpz_to_unsigned_long(const mpz_t ival,
				       unsigned long *val) const
{
  if (mpz_sgn(ival) < 0)
    return NC_UL_NEGATIVE;
  unsigned long ui = mpz_get_ui(ival);
  if (mpz_cmp_ui(ival, ui) != 0)
    return NC_UL_BIG;
  *val = ui;
  return NC_UL_VALID;
}

// Express floating point value as unsigned long if possible.

Numeric_constant::To_unsigned_long
Numeric_constant::mpfr_to_unsigned_long(const mpfr_t fval,
					unsigned long *val) const
{
  if (!mpfr_integer_p(fval))
    return NC_UL_NOTINT;
  mpz_t ival;
  mpz_init(ival);
  mpfr_get_z(ival, fval, MPFR_RNDN);
  To_unsigned_long ret = this->mpz_to_unsigned_long(ival, val);
  mpz_clear(ival);
  return ret;
}

// Express value as memory size if possible.

bool
Numeric_constant::to_memory_size(int64_t* val) const
{
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      return this->mpz_to_memory_size(this->u_.int_val, val);
    case NC_FLOAT:
      return this->mpfr_to_memory_size(this->u_.float_val, val);
    case NC_COMPLEX:
      if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
	return false;
      return this->mpfr_to_memory_size(mpc_realref(this->u_.complex_val), val);
    default:
      go_unreachable();
    }
}

// Express integer as memory size if possible.

bool
Numeric_constant::mpz_to_memory_size(const mpz_t ival, int64_t* val) const
{
  if (mpz_sgn(ival) < 0)
    return false;
  if (mpz_fits_slong_p(ival))
    {
      *val = static_cast<int64_t>(mpz_get_si(ival));
      return true;
    }

  // Test >= 64, not > 64, because an int64_t can hold 63 bits of a
  // positive value.
  if (mpz_sizeinbase(ival, 2) >= 64)
    return false;

  mpz_t q, r;
  mpz_init(q);
  mpz_init(r);
  mpz_tdiv_q_2exp(q, ival, 32);
  mpz_tdiv_r_2exp(r, ival, 32);
  go_assert(mpz_fits_ulong_p(q) && mpz_fits_ulong_p(r));
  *val = ((static_cast<int64_t>(mpz_get_ui(q)) << 32)
	  + static_cast<int64_t>(mpz_get_ui(r)));
  mpz_clear(r);
  mpz_clear(q);
  return true;
}

// Express floating point value as memory size if possible.

bool
Numeric_constant::mpfr_to_memory_size(const mpfr_t fval, int64_t* val) const
{
  if (!mpfr_integer_p(fval))
    return false;
  mpz_t ival;
  mpz_init(ival);
  mpfr_get_z(ival, fval, MPFR_RNDN);
  bool ret = this->mpz_to_memory_size(ival, val);
  mpz_clear(ival);
  return ret;
}

// Convert value to integer if possible.

bool
Numeric_constant::to_int(mpz_t* val) const
{
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      mpz_init_set(*val, this->u_.int_val);
      return true;
    case NC_FLOAT:
      if (!mpfr_integer_p(this->u_.float_val))
	return false;
      mpz_init(*val);
      mpfr_get_z(*val, this->u_.float_val, MPFR_RNDN);
      return true;
    case NC_COMPLEX:
      if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val))
	  || !mpfr_integer_p(mpc_realref(this->u_.complex_val)))
	return false;
      mpz_init(*val);
      mpfr_get_z(*val, mpc_realref(this->u_.complex_val), MPFR_RNDN);
      return true;
    default:
      go_unreachable();
    }
}

// Convert value to floating point if possible.

bool
Numeric_constant::to_float(mpfr_t* val) const
{
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      mpfr_init_set_z(*val, this->u_.int_val, MPFR_RNDN);
      return true;
    case NC_FLOAT:
      mpfr_init_set(*val, this->u_.float_val, MPFR_RNDN);
      return true;
    case NC_COMPLEX:
      if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
	return false;
      mpfr_init_set(*val, mpc_realref(this->u_.complex_val), MPFR_RNDN);
      return true;
    default:
      go_unreachable();
    }
}

// Convert value to complex.

bool
Numeric_constant::to_complex(mpc_t* val) const
{
  mpc_init2(*val, mpc_precision);
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      mpc_set_z(*val, this->u_.int_val, MPC_RNDNN);
      return true;
    case NC_FLOAT:
      mpc_set_fr(*val, this->u_.float_val, MPC_RNDNN);
      return true;
    case NC_COMPLEX:
      mpc_set(*val, this->u_.complex_val, MPC_RNDNN);
      return true;
    default:
      go_unreachable();
    }
}

// Get the type.

Type*
Numeric_constant::type() const
{
  if (this->type_ != NULL)
    return this->type_;
  switch (this->classification_)
    {
    case NC_INT:
      return Type::make_abstract_integer_type();
    case NC_RUNE:
      return Type::make_abstract_character_type();
    case NC_FLOAT:
      return Type::make_abstract_float_type();
    case NC_COMPLEX:
      return Type::make_abstract_complex_type();
    default:
      go_unreachable();
    }
}

// If the constant can be expressed in TYPE, then set the type of the
// constant to TYPE and return true.  Otherwise return false, and, if
// ISSUE_ERROR is true, report an appropriate error message.

bool
Numeric_constant::set_type(Type* type, bool issue_error, Location loc)
{
  bool ret;
  if (type == NULL || type->is_error())
    ret = true;
  else if (type->integer_type() != NULL)
    ret = this->check_int_type(type->integer_type(), issue_error, loc);
  else if (type->float_type() != NULL)
    ret = this->check_float_type(type->float_type(), issue_error, loc);
  else if (type->complex_type() != NULL)
    ret = this->check_complex_type(type->complex_type(), issue_error, loc);
  else
    {
      ret = false;
      if (issue_error)
        go_assert(saw_errors());
    }
  if (ret)
    this->type_ = type;
  return ret;
}

// Check whether the constant can be expressed in an integer type.

bool
Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
				 Location location)
{
  mpz_t val;
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      mpz_init_set(val, this->u_.int_val);
      break;

    case NC_FLOAT:
      if (!mpfr_integer_p(this->u_.float_val))
	{
	  if (issue_error)
            {
              go_error_at(location,
                          "floating-point constant truncated to integer");
              this->set_invalid();
            }
	  return false;
	}
      mpz_init(val);
      mpfr_get_z(val, this->u_.float_val, MPFR_RNDN);
      break;

    case NC_COMPLEX:
      if (!mpfr_integer_p(mpc_realref(this->u_.complex_val))
	  || !mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
	{
	  if (issue_error)
            {
              go_error_at(location, "complex constant truncated to integer");
              this->set_invalid();
            }
	  return false;
	}
      mpz_init(val);
      mpfr_get_z(val, mpc_realref(this->u_.complex_val), MPFR_RNDN);
      break;

    default:
      go_unreachable();
    }

  bool ret;
  if (type->is_abstract())
    ret = true;
  else
    {
      int bits = mpz_sizeinbase(val, 2);
      if (type->is_unsigned())
	{
	  // For an unsigned type we can only accept a nonnegative
	  // number, and we must be able to represents at least BITS.
	  ret = mpz_sgn(val) >= 0 && bits <= type->bits();
	}
      else
	{
	  // For a signed type we need an extra bit to indicate the
	  // sign.  We have to handle the most negative integer
	  // specially.
	  ret = (bits + 1 <= type->bits()
		 || (bits <= type->bits()
		     && mpz_sgn(val) < 0
		     && (mpz_scan1(val, 0)
			 == static_cast<unsigned long>(type->bits() - 1))
		     && mpz_scan0(val, type->bits()) == ULONG_MAX));
	}
    }

  if (!ret && issue_error)
    {
      go_error_at(location, "integer constant overflow");
      this->set_invalid();
    }

  return ret;
}

// Check whether the constant can be expressed in a floating point
// type.

bool
Numeric_constant::check_float_type(Float_type* type, bool issue_error,
				   Location location)
{
  mpfr_t val;
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      mpfr_init_set_z(val, this->u_.int_val, MPFR_RNDN);
      break;

    case NC_FLOAT:
      mpfr_init_set(val, this->u_.float_val, MPFR_RNDN);
      break;

    case NC_COMPLEX:
      if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
	{
	  if (issue_error)
            {
              this->set_invalid();
              go_error_at(location,
			  "complex constant truncated to floating-point");
            }
	  return false;
	}
      mpfr_init_set(val, mpc_realref(this->u_.complex_val), MPFR_RNDN);
      break;

    default:
      go_unreachable();
    }

  bool ret;
  if (type->is_abstract())
    ret = true;
  else if (mpfr_nan_p(val) || mpfr_inf_p(val) || mpfr_zero_p(val))
    {
      // A NaN or Infinity always fits in the range of the type.
      ret = true;
    }
  else
    {
      mpfr_exp_t exp = mpfr_get_exp(val);
      mpfr_exp_t max_exp;
      switch (type->bits())
	{
	case 32:
	  max_exp = 128;
	  break;
	case 64:
	  max_exp = 1024;
	  break;
	default:
	  go_unreachable();
	}

      ret = exp <= max_exp;

      if (ret)
	{
	  // Round the constant to the desired type.
	  mpfr_t t;
	  mpfr_init(t);
	  switch (type->bits())
	    {
	    case 32:
	      mpfr_set_prec(t, 24);
	      break;
	    case 64:
	      mpfr_set_prec(t, 53);
	      break;
	    default:
	      go_unreachable();
	    }
	  mpfr_set(t, val, MPFR_RNDN);
	  mpfr_set(val, t, MPFR_RNDN);
	  mpfr_clear(t);

	  this->set_float(type, val);
	}
    }

  mpfr_clear(val);

  if (!ret && issue_error)
    {
      go_error_at(location, "floating-point constant overflow");
      this->set_invalid();
    }

  return ret;
}

// Check whether the constant can be expressed in a complex type.

bool
Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
				     Location location)
{
  if (type->is_abstract())
    return true;

  mpfr_exp_t max_exp;
  switch (type->bits())
    {
    case 64:
      max_exp = 128;
      break;
    case 128:
      max_exp = 1024;
      break;
    default:
      go_unreachable();
    }

  mpc_t val;
  mpc_init2(val, mpc_precision);
  switch (this->classification_)
    {
    case NC_INT:
    case NC_RUNE:
      mpc_set_z(val, this->u_.int_val, MPC_RNDNN);
      break;

    case NC_FLOAT:
      mpc_set_fr(val, this->u_.float_val, MPC_RNDNN);
      break;

    case NC_COMPLEX:
      mpc_set(val, this->u_.complex_val, MPC_RNDNN);
      break;

    default:
      go_unreachable();
    }

  bool ret = true;
  if (!mpfr_nan_p(mpc_realref(val))
      && !mpfr_inf_p(mpc_realref(val))
      && !mpfr_zero_p(mpc_realref(val))
      && mpfr_get_exp(mpc_realref(val)) > max_exp)
    {
      if (issue_error)
        {
          go_error_at(location, "complex real part overflow");
          this->set_invalid();
        }
      ret = false;
    }

  if (!mpfr_nan_p(mpc_imagref(val))
      && !mpfr_inf_p(mpc_imagref(val))
      && !mpfr_zero_p(mpc_imagref(val))
      && mpfr_get_exp(mpc_imagref(val)) > max_exp)
    {
      if (issue_error)
        {
          go_error_at(location, "complex imaginary part overflow");
          this->set_invalid();
        }
      ret = false;
    }

  if (ret)
    {
      // Round the constant to the desired type.
      mpc_t t;
      switch (type->bits())
	{
	case 64:
	  mpc_init2(t, 24);
	  break;
	case 128:
	  mpc_init2(t, 53);
	  break;
	default:
	  go_unreachable();
	}
      mpc_set(t, val, MPC_RNDNN);
      mpc_set(val, t, MPC_RNDNN);
      mpc_clear(t);

      this->set_complex(type, val);
    }

  mpc_clear(val);

  return ret;
}

// Return an Expression for this value.

Expression*
Numeric_constant::expression(Location loc) const
{
  switch (this->classification_)
    {
    case NC_INT:
      return Expression::make_integer_z(&this->u_.int_val, this->type_, loc);
    case NC_RUNE:
      return Expression::make_character(&this->u_.int_val, this->type_, loc);
    case NC_FLOAT:
      return Expression::make_float(&this->u_.float_val, this->type_, loc);
    case NC_COMPLEX:
      return Expression::make_complex(&this->u_.complex_val, this->type_, loc);
    case NC_INVALID:
      go_assert(saw_errors());
      return Expression::make_error(loc);
    default:
      go_unreachable();
    }
}

// Calculate a hash code with a given seed.

unsigned int
Numeric_constant::hash(unsigned int seed) const
{
  unsigned long val;
  const unsigned int PRIME = 97;
  long e = 0;
  double f = 1.0;
  mpfr_t m;

  switch (this->classification_)
    {
    case NC_INVALID:
      return PRIME;
    case NC_INT:
    case NC_RUNE:
      val = mpz_get_ui(this->u_.int_val);
      break;
    case NC_COMPLEX:
      mpfr_init(m);
      mpc_abs(m, this->u_.complex_val, MPFR_RNDN);
      val = mpfr_get_ui(m, MPFR_RNDN);
      mpfr_clear(m);
      break;
    case NC_FLOAT:
      f = mpfr_get_d_2exp(&e, this->u_.float_val, MPFR_RNDN) * 4294967295.0;
      val = static_cast<unsigned long>(e + static_cast<long>(f));
      break;
    default:
      go_unreachable();
    }

  return (static_cast<unsigned int>(val) + seed) * PRIME;
}
