// wb.cc -- Add write barriers as needed.

// Copyright 2017 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 "go-c.h"
#include "go-diagnostics.h"
#include "operator.h"
#include "lex.h"
#include "types.h"
#include "expressions.h"
#include "statements.h"
#include "runtime.h"
#include "gogo.h"

// Mark variables whose addresses are taken and do some other
// cleanups.  This has to be done before the write barrier pass and
// after the escape analysis pass.  It would be nice to do this
// elsewhere but there isn't an obvious place.

class Mark_address_taken : public Traverse
{
 public:
  Mark_address_taken(Gogo* gogo)
    : Traverse(traverse_functions
	       | traverse_statements
	       | traverse_expressions),
      gogo_(gogo), function_(NULL)
  { }

  int
  function(Named_object*);

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

  int
  expression(Expression**);

 private:
  // General IR.
  Gogo* gogo_;
  // The function we are traversing.
  Named_object* function_;
};

// Record a function.

int
Mark_address_taken::function(Named_object* no)
{
  go_assert(this->function_ == NULL);
  this->function_ = no;
  int t = no->func_value()->traverse(this);
  this->function_ = NULL;

  if (t == TRAVERSE_EXIT)
    return t;
  return TRAVERSE_SKIP_COMPONENTS;
}

// Traverse a statement.

int
Mark_address_taken::statement(Block* block, size_t* pindex, Statement* s)
{
  // If this is an assignment of the form s = append(s, ...), expand
  // it now, so that we can assign it to the left hand side in the
  // middle of the expansion and possibly skip a write barrier.
  Assignment_statement* as = s->assignment_statement();
  if (as != NULL && !as->lhs()->is_sink_expression())
    {
      Call_expression* rce = as->rhs()->call_expression();
      if (rce != NULL
	  && rce->builtin_call_expression() != NULL
	  && (rce->builtin_call_expression()->code()
	      == Builtin_call_expression::BUILTIN_APPEND)
          && Expression::is_same_variable(as->lhs(), rce->args()->front()))
	{
	  Statement_inserter inserter = Statement_inserter(block, pindex);
	  Expression* a =
	    rce->builtin_call_expression()->flatten_append(this->gogo_,
							   this->function_,
							   &inserter,
							   as->lhs(),
							   block);
	  go_assert(a == NULL);
	  // That does the assignment, so remove this statement.
	  Expression* e = Expression::make_boolean(true, s->location());
	  Statement* dummy = Statement::make_statement(e, true);
	  block->replace_statement(*pindex, dummy);
	}
    }
  return TRAVERSE_CONTINUE;
}

// Mark variable addresses taken.

int
Mark_address_taken::expression(Expression** pexpr)
{
  Expression* expr = *pexpr;
  Unary_expression* ue = expr->unary_expression();
  if (ue != NULL)
    ue->check_operand_address_taken(this->gogo_);

  Array_index_expression* aie = expr->array_index_expression();
  if (aie != NULL
      && aie->end() != NULL
      && !aie->array()->type()->is_slice_type())
    {
      // Slice of an array. The escape analysis models this with
      // a child Node representing the address of the array.
      bool escapes = false;
      Node* n = Node::make_node(expr);
      if (n->child() == NULL
          || (n->child()->encoding() & ESCAPE_MASK) != Node::ESCAPE_NONE)
        escapes = true;
      aie->array()->address_taken(escapes);
    }

  if (expr->allocation_expression() != NULL)
    {
      Node* n = Node::make_node(expr);
      if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
        expr->allocation_expression()->set_allocate_on_stack();
    }
  if (expr->heap_expression() != NULL)
    {
      Node* n = Node::make_node(expr);
      if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
        expr->heap_expression()->set_allocate_on_stack();
    }
  if (expr->slice_literal() != NULL)
    {
      Node* n = Node::make_node(expr);
      if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
        expr->slice_literal()->set_storage_does_not_escape();
    }

  // Rewrite non-escaping makeslice with constant size to stack allocation.
  Slice_value_expression* sve = expr->slice_value_expression();
  if (sve != NULL)
    {
      std::pair<Call_expression*, Temporary_statement*> p =
        Expression::find_makeslice_call(sve);
      Call_expression* call = p.first;
      Temporary_statement* ts = p.second;
      if (call != NULL
	  && Node::make_node(call)->encoding() == Node::ESCAPE_NONE)
        {
          Expression* len_arg = call->args()->at(1);
          Expression* cap_arg = call->args()->at(2);
          Numeric_constant nclen;
          Numeric_constant nccap;
          unsigned long vlen;
          unsigned long vcap;
          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)
            {
	      // Stack allocate an array and make a slice value from it.
              Location loc = expr->location();
              Type* elmt_type = expr->type()->array_type()->element_type();
              Expression* len_expr =
                Expression::make_integer_ul(vcap, cap_arg->type(), loc);
              Type* array_type = Type::make_array_type(elmt_type, len_expr);
              Expression* alloc = Expression::make_allocation(array_type, loc);
              alloc->allocation_expression()->set_allocate_on_stack();
	      Type* ptr_type = Type::make_pointer_type(elmt_type);
	      Expression* ptr = Expression::make_unsafe_cast(ptr_type, alloc,
							     loc);
	      Expression* slice =
		Expression::make_slice_value(expr->type(), ptr, len_arg,
					     cap_arg, loc);
              *pexpr = slice;
              if (ts != NULL && ts->uses() == 1)
                ts->set_init(Expression::make_nil(loc));
            }
        }
    }
  return TRAVERSE_CONTINUE;
}

// Check variables and closures do not escape when compiling runtime.

class Check_escape : public Traverse
{
 public:
  Check_escape()
    : Traverse(traverse_expressions | traverse_variables)
  { }

  int
  expression(Expression**);

  int
  variable(Named_object*);
};

int
Check_escape::variable(Named_object* no)
{
  if ((no->is_variable() && no->var_value()->is_in_heap())
      || (no->is_result_variable()
          && no->result_var_value()->is_in_heap()))
    go_error_at(no->location(),
                "%s escapes to heap, not allowed in runtime",
                no->message_name().c_str());
  return TRAVERSE_CONTINUE;
}

int
Check_escape::expression(Expression** pexpr)
{
  Expression* expr = *pexpr;
  Func_expression* fe = expr->func_expression();
  if (fe != NULL && fe->closure() != NULL)
    {
      Node* n = Node::make_node(expr);
      if (n->encoding() == Node::ESCAPE_HEAP)
        go_error_at(expr->location(),
                    "heap-allocated closure, not allowed in runtime");
    }
  return TRAVERSE_CONTINUE;
}

// Collect all writebarrierrec functions.  This is used when compiling
// the runtime package, to propagate //go:nowritebarrierrec.

class Collect_writebarrierrec_functions : public Traverse
{
 public:
  Collect_writebarrierrec_functions(std::vector<Named_object*>* worklist)
    : Traverse(traverse_functions),
      worklist_(worklist)
  { }

 private:
  int
  function(Named_object*);

  // The collected functions are put here.
  std::vector<Named_object*>* worklist_;
};

int
Collect_writebarrierrec_functions::function(Named_object* no)
{
  if (no->is_function()
      && no->func_value()->enclosing() == NULL
      && (no->func_value()->pragmas() & GOPRAGMA_NOWRITEBARRIERREC) != 0)
    {
      go_assert((no->func_value()->pragmas() & GOPRAGMA_MARK) == 0);
      this->worklist_->push_back(no);
    }
  return TRAVERSE_CONTINUE;
}

// Collect all callees of this function.  We only care about locally
// defined, known, functions.

class Collect_callees : public Traverse
{
 public:
  Collect_callees(std::vector<Named_object*>* worklist)
    : Traverse(traverse_expressions),
      worklist_(worklist)
  { }

 private:
  int
  expression(Expression**);

  // The collected callees are put here.
  std::vector<Named_object*>* worklist_;
};

int
Collect_callees::expression(Expression** pexpr)
{
  Call_expression* ce = (*pexpr)->call_expression();
  if (ce != NULL)
    {
      Func_expression* fe = ce->fn()->func_expression();
      if (fe != NULL)
	{
	  Named_object* no = fe->named_object();
	  if (no->package() == NULL && no->is_function())
	    {
	      // The function runtime.systemstack is special, in that
	      // it is a common way to call a function in the runtime:
	      // mark its argument if we can.
	      if (Gogo::unpack_hidden_name(no->name()) != "systemstack")
		this->worklist_->push_back(no);
	      else if (ce->args()->size() > 0)
		{
		  fe = ce->args()->front()->func_expression();
		  if (fe != NULL)
		    {
		      no = fe->named_object();
		      if (no->package() == NULL && no->is_function())
			this->worklist_->push_back(no);
		    }
		}
	    }
	}
    }
  return TRAVERSE_CONTINUE;
}

// When compiling the runtime package, propagate //go:nowritebarrierrec
// annotations.  A function marked as //go:nowritebarrierrec does not
// permit write barriers, and also all the functions that it calls,
// recursively, do not permit write barriers.  Except that a
// //go:yeswritebarrierrec annotation permits write barriers even if
// called by a //go:nowritebarrierrec function.  Here we turn
// //go:nowritebarrierrec into //go:nowritebarrier, as appropriate.

void
Gogo::propagate_writebarrierrec()
{
  std::vector<Named_object*> worklist;
  Collect_writebarrierrec_functions cwf(&worklist);
  this->traverse(&cwf);

  Collect_callees cc(&worklist);

  while (!worklist.empty())
    {
      Named_object* no = worklist.back();
      worklist.pop_back();

      unsigned int pragmas = no->func_value()->pragmas();
      if ((pragmas & GOPRAGMA_MARK) != 0)
	{
	  // We've already seen this function.
	  continue;
	}
      if ((pragmas & GOPRAGMA_YESWRITEBARRIERREC) != 0)
	{
	  // We don't want to propagate //go:nowritebarrierrec into
	  // this function or it's callees.
	  continue;
	}

      no->func_value()->set_pragmas(pragmas
				    | GOPRAGMA_NOWRITEBARRIER
				    | GOPRAGMA_MARK);

      no->func_value()->traverse(&cc);
    }
}

// Add write barriers to the IR.  This are required by the concurrent
// garbage collector.  A write barrier is needed for any write of a
// pointer into memory controlled by the garbage collector.  Write
// barriers are not required for writes to local variables that live
// on the stack.  Write barriers are only required when the runtime
// enables them, which can be checked using a run time check on
// runtime.writeBarrier.enabled.
//
// Essentially, for each assignment A = B, where A is or contains a
// pointer, and where A is not, or at any rate may not be, a stack
// variable, we rewrite it into
//     if runtime.writeBarrier.enabled {
//         typedmemmove(typeof(A), &A, &B)
//     } else {
//         A = B
//     }
//
// The test of runtime.writeBarrier.Enabled is implemented by treating
// the variable as a *uint32, and testing *runtime.writeBarrier != 0.
// This is compatible with the definition in the runtime package.
//
// For types that are pointer shared (pointers, maps, chans, funcs),
// we replaced the call to typedmemmove with gcWriteBarrier(&A, B).
// As far as the GC is concerned, all pointers are the same, so it
// doesn't need the type descriptor.
//
// There are possible optimizations that are not implemented.
//
// runtime.writeBarrier can only change when the goroutine is
// preempted, which in practice means when a call is made into the
// runtime package, so we could optimize by only testing it once
// between function calls.
//
// A slice could be handled with a call to gcWriteBarrier plus two
// integer moves.

// Traverse the IR adding write barriers.

class Write_barriers : public Traverse
{
 public:
  Write_barriers(Gogo* gogo)
    : Traverse(traverse_functions
	       | traverse_blocks
	       | traverse_variables
	       | traverse_statements),
      gogo_(gogo), function_(NULL), statements_added_(),
      nonwb_pointers_()
  { }

  int
  function(Named_object*);

  int
  block(Block*);

  int
  variable(Named_object*);

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

 private:
  // General IR.
  Gogo* gogo_;
  // Current function.
  Function* function_;
  // Statements introduced.
  Statement_inserter::Statements statements_added_;
  // Within a single block, pointer variables that point to values
  // that do not need write barriers.
  Unordered_set(const Named_object*) nonwb_pointers_;
};

// Traverse a function.  Just record it for later.

int
Write_barriers::function(Named_object* no)
{
  go_assert(this->function_ == NULL);
  this->function_ = no->func_value();
  int t = this->function_->traverse(this);
  this->function_ = NULL;

  if (t == TRAVERSE_EXIT)
    return t;
  return TRAVERSE_SKIP_COMPONENTS;
}

// Traverse a block.  Clear anything we know about local pointer
// variables.

int
Write_barriers::block(Block*)
{
  this->nonwb_pointers_.clear();
  return TRAVERSE_CONTINUE;
}

// Insert write barriers for a global variable: ensure that variable
// initialization is handled correctly.  This is rarely needed, since
// we currently don't enable background GC until after all global
// variables are initialized.  But we do need this if an init function
// calls runtime.GC.

int
Write_barriers::variable(Named_object* no)
{
  // We handle local variables in the variable declaration statement.
  // We only have to handle global variables here.
  if (!no->is_variable())
    return TRAVERSE_CONTINUE;
  Variable* var = no->var_value();
  if (!var->is_global())
    return TRAVERSE_CONTINUE;

  // Nothing to do if there is no initializer.
  Expression* init = var->init();
  if (init == NULL)
    return TRAVERSE_CONTINUE;

  // Nothing to do for variables that do not contain any pointers.
  if (!var->type()->has_pointer())
    return TRAVERSE_CONTINUE;

  // Nothing to do if the initializer is static.
  init = Expression::make_cast(var->type(), init, var->location());
  if (!var->has_pre_init() && init->is_static_initializer())
    return TRAVERSE_CONTINUE;

  // Nothing to do for a type that can not be in the heap, or a
  // pointer to a type that can not be in the heap.
  if (!var->type()->in_heap())
    return TRAVERSE_CONTINUE;
  if (var->type()->points_to() != NULL && !var->type()->points_to()->in_heap())
    return TRAVERSE_CONTINUE;

  // Otherwise change the initializer into a pre_init assignment
  // statement with a write barrier.

  // We can't check for a dependency of the variable on itself after
  // we make this change, because the preinit statement will always
  // depend on the variable (since it assigns to it).  So check for a
  // self-dependency now.
  this->gogo_->check_self_dep(no);

  // Replace the initializer.
  Location loc = init->location();
  Expression* ref = Expression::make_var_reference(no, loc);

  Statement_inserter inserter(this->gogo_, var, &this->statements_added_);
  Statement* s = this->gogo_->assign_with_write_barrier(NULL, NULL, &inserter,
							ref, init, loc);
  this->statements_added_.insert(s);

  var->add_preinit_statement(this->gogo_, s);
  var->clear_init();

  return TRAVERSE_CONTINUE;
}

// Insert write barriers for statements.

int
Write_barriers::statement(Block* block, size_t* pindex, Statement* s)
{
  if (this->statements_added_.find(s) != this->statements_added_.end())
    return TRAVERSE_SKIP_COMPONENTS;

  switch (s->classification())
    {
    default:
      break;

    case Statement::STATEMENT_VARIABLE_DECLARATION:
      {
	Variable_declaration_statement* vds =
	  s->variable_declaration_statement();
	Named_object* no = vds->var();
	Variable* var = no->var_value();

	// We may need to emit a write barrier for the initialization
	// of the variable.

	// Nothing to do for a variable with no initializer.
	Expression* init = var->init();
	if (init == NULL)
	  break;

	// Nothing to do if the variable is not in the heap.  Only
	// local variables get declaration statements, and local
	// variables on the stack do not require write barriers.
	if (!var->is_in_heap())
          {
	    // If this is a pointer variable, and assigning through
	    // the initializer does not require a write barrier,
	    // record that fact.
	    if (var->type()->points_to() != NULL
		&& this->gogo_->is_nonwb_pointer(init, &this->nonwb_pointers_))
	      this->nonwb_pointers_.insert(no);

	    break;
          }

	// Nothing to do if the variable does not contain any pointers.
	if (!var->type()->has_pointer())
	  break;

	// Nothing to do for a type that can not be in the heap, or a
	// pointer to a type that can not be in the heap.
	if (!var->type()->in_heap())
	  break;
	if (var->type()->points_to() != NULL
	    && !var->type()->points_to()->in_heap())
	  break;

	// Otherwise initialize the variable with a write barrier.

	Function* function = this->function_;
	Location loc = init->location();
	Statement_inserter inserter(block, pindex, &this->statements_added_);

	// Insert the variable declaration statement with no
	// initializer, so that the variable exists.
	var->clear_init();
	inserter.insert(s);

	// Create a statement that initializes the variable with a
	// write barrier.
	Expression* ref = Expression::make_var_reference(no, loc);
	Statement* assign = this->gogo_->assign_with_write_barrier(function,
								   block,
								   &inserter,
								   ref, init,
								   loc);
        this->statements_added_.insert(assign);

	// Replace the old variable declaration statement with the new
	// initialization.
	block->replace_statement(*pindex, assign);
      }
      break;

    case Statement::STATEMENT_ASSIGNMENT:
      {
	Assignment_statement* as = s->assignment_statement();

	Expression* lhs = as->lhs();
	Expression* rhs = as->rhs();

	// Keep track of variables whose values do not escape.
	Var_expression* lhsve = lhs->var_expression();
	if (lhsve != NULL && lhsve->type()->points_to() != NULL)
	  {
	    Named_object* no = lhsve->named_object();
	    if (this->gogo_->is_nonwb_pointer(rhs, &this->nonwb_pointers_))
	      this->nonwb_pointers_.insert(no);
	    else
	      this->nonwb_pointers_.erase(no);
	  }

	if (as->omit_write_barrier())
	  break;

	// We may need to emit a write barrier for the assignment.

	if (!this->gogo_->assign_needs_write_barrier(lhs,
						     &this->nonwb_pointers_))
	  break;

	// Change the assignment to use a write barrier.
	Function* function = this->function_;
	Location loc = as->location();
	Statement_inserter inserter =
            Statement_inserter(block, pindex, &this->statements_added_);
	Statement* assign = this->gogo_->assign_with_write_barrier(function,
								   block,
								   &inserter,
								   lhs, rhs,
								   loc);
        this->statements_added_.insert(assign);
	block->replace_statement(*pindex, assign);
      }
      break;
    }

  return TRAVERSE_CONTINUE;
}

// The write barrier pass.

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

  Mark_address_taken mat(this);
  this->traverse(&mat);

  if (this->compiling_runtime() && this->package_name() == "runtime")
    {
      this->propagate_writebarrierrec();

      Check_escape chk;
      this->traverse(&chk);
    }

  Write_barriers wb(this);
  this->traverse(&wb);
}

// Return the runtime.writeBarrier variable.

Named_object*
Gogo::write_barrier_variable()
{
  static Named_object* write_barrier_var;
  if (write_barrier_var == NULL)
    {
      Location bloc = Linemap::predeclared_location();

      Type* bool_type = Type::lookup_bool_type();
      Array_type* pad_type =
	Type::make_array_type(Type::lookup_integer_type("byte"),
			      Expression::make_integer_ul(3, NULL, bloc));
      Type* uint64_type = Type::lookup_integer_type("uint64");
      Type* wb_type = Type::make_builtin_struct_type(5,
						     "enabled", bool_type,
						     "pad", pad_type,
						     "needed", bool_type,
						     "cgo", bool_type,
						     "alignme", uint64_type);

      Variable* var = new Variable(wb_type, NULL,
				    true, false, false, bloc);

      bool add_to_globals;
      Package* package = this->add_imported_package("runtime", "_", false,
						    "runtime", "runtime",
						    bloc, &add_to_globals);
      write_barrier_var = Named_object::make_variable("writeBarrier",
						      package, var);
    }

  return write_barrier_var;
}

// Return whether an assignment that sets LHS needs a write barrier.
// NONWB_POINTERS is a set of variables that point to values that do
// not need write barriers.

bool
Gogo::assign_needs_write_barrier(
    Expression* lhs,
    Unordered_set(const Named_object*)* nonwb_pointers)
{
  // Nothing to do if the variable does not contain any pointers.
  if (!lhs->type()->has_pointer())
    return false;

  // An assignment to a field or an array index is handled like an
  // assignment to the struct.
  while (true)
    {
      // Nothing to do for a type that can not be in the heap, or a
      // pointer to a type that can not be in the heap.  We check this
      // at each level of a struct.
      if (!lhs->type()->in_heap())
	return false;
      if (lhs->type()->points_to() != NULL
	  && !lhs->type()->points_to()->in_heap())
	return false;

      // For a struct assignment, we don't need a write barrier if all
      // the field types can not be in the heap.
      Struct_type* st = lhs->type()->struct_type();
      if (st != NULL)
	{
	  bool in_heap = false;
	  const Struct_field_list* fields = st->fields();
	  for (Struct_field_list::const_iterator p = fields->begin();
	       p != fields->end();
	       p++)
	    {
	      Type* ft = p->type();
	      if (!ft->has_pointer())
		continue;
	      if (!ft->in_heap())
		continue;
	      if (ft->points_to() != NULL && !ft->points_to()->in_heap())
		continue;
	      in_heap = true;
	      break;
	    }
	  if (!in_heap)
	    return false;
	}

      Field_reference_expression* fre = lhs->field_reference_expression();
      if (fre != NULL)
	{
	  lhs = fre->expr();
	  continue;
	}

      Array_index_expression* aie = lhs->array_index_expression();
      if (aie != NULL
	  && aie->end() == NULL
	  && !aie->array()->type()->is_slice_type())
	{
	  lhs = aie->array();
	  continue;
	}

      break;
    }

  // Nothing to do for an assignment to a temporary.
  if (lhs->temporary_reference_expression() != NULL)
    return false;

  // Nothing to do for an assignment to a sink.
  if (lhs->is_sink_expression())
    return false;

  // Nothing to do for an assignment to a local variable that is not
  // on the heap.
  Var_expression* ve = lhs->var_expression();
  if (ve != NULL)
    {
      Named_object* no = ve->named_object();
      if (no->is_variable())
	{
	  Variable* var = no->var_value();
	  if (!var->is_global() && !var->is_in_heap())
	    return false;
	}
      else if (no->is_result_variable())
	{
	  Result_variable* rvar = no->result_var_value();
	  if (!rvar->is_in_heap())
	    return false;
	}
    }

  // Nothing to do for an assignment to *(convert(&x)) where
  // x is local variable or a temporary variable.
  Unary_expression* ue = lhs->unary_expression();
  if (ue != NULL
      && ue->op() == OPERATOR_MULT
      && this->is_nonwb_pointer(ue->operand(), nonwb_pointers))
    return false;

  // Write barrier needed in other cases.
  return true;
}

// Return whether EXPR is the address of a variable that can be set
// without a write barrier.  That is, if this returns true, then an
// assignment to *EXPR does not require a write barrier.
// NONWB_POINTERS is a set of variables that point to values that do
// not need write barriers.

bool
Gogo::is_nonwb_pointer(Expression* expr,
		       Unordered_set(const Named_object*)* nonwb_pointers)
{
  while (true)
    {
      if (expr->conversion_expression() != NULL)
	expr = expr->conversion_expression()->expr();
      else if (expr->unsafe_conversion_expression() != NULL)
	expr = expr->unsafe_conversion_expression()->expr();
      else
	break;
    }

  Var_expression* ve = expr->var_expression();
  if (ve != NULL
      && nonwb_pointers != NULL
      && nonwb_pointers->find(ve->named_object()) != nonwb_pointers->end())
    return true;

  Unary_expression* ue = expr->unary_expression();
  if (ue == NULL || ue->op() != OPERATOR_AND)
    return false;
  if (this->assign_needs_write_barrier(ue->operand(), nonwb_pointers))
    return false;
  return true;
}

// Return a statement that sets LHS to RHS using a write barrier.
// ENCLOSING is the enclosing block.

Statement*
Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
				Statement_inserter* inserter, Expression* lhs,
				Expression* rhs, Location loc)
{
  if (function != NULL && (function->pragmas() & GOPRAGMA_NOWRITEBARRIER) != 0)
    go_error_at(loc, "write barrier prohibited");

  Type* type = lhs->type();
  go_assert(type->has_pointer());

  Expression* addr;
  if (lhs->unary_expression() != NULL
      && lhs->unary_expression()->op() == OPERATOR_MULT)
    addr = lhs->unary_expression()->operand();
  else
    {
      addr = Expression::make_unary(OPERATOR_AND, lhs, loc);
      addr->unary_expression()->set_does_not_escape();
    }
  Temporary_statement* lhs_temp = Statement::make_temporary(NULL, addr, loc);
  lhs_temp->determine_types(this);
  inserter->insert(lhs_temp);
  lhs = Expression::make_temporary_reference(lhs_temp, loc);

  if (!Type::are_identical(type, rhs->type(),
			   Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			   NULL)
      && rhs->type()->interface_type() != NULL
      && !rhs->is_multi_eval_safe())
    {
      // May need a temporary for interface conversion.
      Temporary_statement* temp = Statement::make_temporary(NULL, rhs, loc);
      temp->determine_types(this);
      inserter->insert(temp);
      rhs = Expression::make_temporary_reference(temp, loc);
    }
  rhs = Expression::convert_for_assignment(this, type, rhs, loc);
  Temporary_statement* rhs_temp = NULL;
  if (!rhs->is_multi_eval_safe())
    {
      rhs_temp = Statement::make_temporary(NULL, rhs, loc);
      rhs_temp->determine_types(this);
      inserter->insert(rhs_temp);
      rhs = Expression::make_temporary_reference(rhs_temp, loc);
    }

  Expression* indir =
      Expression::make_dereference(lhs, Expression::NIL_CHECK_DEFAULT, loc);
  Statement* assign = Statement::make_assignment(indir, rhs, loc);

  lhs = Expression::make_temporary_reference(lhs_temp, loc);
  if (rhs_temp != NULL)
    rhs = Expression::make_temporary_reference(rhs_temp, loc);

  Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
  lhs = Expression::make_unsafe_cast(unsafe_ptr_type, lhs, loc);

  Type* uintptr_type = Type::lookup_integer_type("uintptr");
  Expression* call;
  switch (type->base()->classification())
    {
    default:
      go_unreachable();

    case Type::TYPE_ERROR:
      return assign;

    case Type::TYPE_POINTER:
    case Type::TYPE_FUNCTION:
    case Type::TYPE_MAP:
    case Type::TYPE_CHANNEL:
      {
	// These types are all represented by a single pointer.
	rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
	call = Runtime::make_call(this, Runtime::GCWRITEBARRIER, loc, 2,
				  lhs, rhs);
      }
      break;

    case Type::TYPE_STRING:
      {
        // Assign the length field directly.
        Expression* llen =
          Expression::make_string_info(indir->copy(),
                                       Expression::STRING_INFO_LENGTH,
                                       loc);
        Expression* rlen =
          Expression::make_string_info(rhs,
                                       Expression::STRING_INFO_LENGTH,
                                       loc);
        Statement* as = Statement::make_assignment(llen, rlen, loc);
	as->determine_types(this);
        inserter->insert(as);

        // Assign the data field with a write barrier.
        lhs =
          Expression::make_string_info(indir->copy(),
                                       Expression::STRING_INFO_DATA,
                                       loc);
        rhs =
          Expression::make_string_info(rhs,
                                       Expression::STRING_INFO_DATA,
                                       loc);
        assign = Statement::make_assignment(lhs, rhs, loc);
        lhs = Expression::make_unary(OPERATOR_AND, lhs, loc);
        rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
        call = Runtime::make_call(this, Runtime::GCWRITEBARRIER, loc, 2,
				  lhs, rhs);
      }
      break;

    case Type::TYPE_INTERFACE:
      {
        // Assign the first field directly.
        // The first field is either a type descriptor or a method table.
        // Type descriptors are either statically created, or created by
        // the reflect package. For the latter the reflect package keeps
        // all references.
        // Method tables are either statically created or persistently
        // allocated.
        // In all cases they don't need a write barrier.
        Expression* ltab =
          Expression::make_interface_info(indir->copy(),
                                          Expression::INTERFACE_INFO_METHODS,
                                          loc);
        Expression* rtab =
          Expression::make_interface_info(rhs,
                                          Expression::INTERFACE_INFO_METHODS,
                                          loc);
        Statement* as = Statement::make_assignment(ltab, rtab, loc);
	as->determine_types(this);
        inserter->insert(as);

        // Assign the data field with a write barrier.
        lhs =
          Expression::make_interface_info(indir->copy(),
                                          Expression::INTERFACE_INFO_OBJECT,
                                          loc);
        rhs =
          Expression::make_interface_info(rhs,
                                          Expression::INTERFACE_INFO_OBJECT,
                                          loc);
        assign = Statement::make_assignment(lhs, rhs, loc);
        lhs = Expression::make_unary(OPERATOR_AND, lhs, loc);
        rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
        call = Runtime::make_call(this, Runtime::GCWRITEBARRIER, loc, 2,
				  lhs, rhs);
      }
      break;

    case Type::TYPE_ARRAY:
      if (type->is_slice_type())
       {
          // Assign the lenth fields directly.
          Expression* llen =
            Expression::make_slice_info(indir->copy(),
                                        Expression::SLICE_INFO_LENGTH,
                                        loc);
          Expression* rlen =
            Expression::make_slice_info(rhs,
                                        Expression::SLICE_INFO_LENGTH,
                                        loc);
          Statement* as = Statement::make_assignment(llen, rlen, loc);
	  as->determine_types(this);
          inserter->insert(as);

          // Assign the capacity fields directly.
          Expression* lcap =
            Expression::make_slice_info(indir->copy(),
                                        Expression::SLICE_INFO_CAPACITY,
                                        loc);
          Expression* rcap =
            Expression::make_slice_info(rhs,
                                        Expression::SLICE_INFO_CAPACITY,
                                        loc);
          as = Statement::make_assignment(lcap, rcap, loc);
	  as->determine_types(this);
          inserter->insert(as);

          // Assign the data field with a write barrier.
          lhs =
            Expression::make_slice_info(indir->copy(),
                                        Expression::SLICE_INFO_VALUE_POINTER,
                                        loc);
          rhs =
            Expression::make_slice_info(rhs,
                                        Expression::SLICE_INFO_VALUE_POINTER,
                                        loc);
          assign = Statement::make_assignment(lhs, rhs, loc);
          lhs = Expression::make_unary(OPERATOR_AND, lhs, loc);
          rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
          call = Runtime::make_call(this, Runtime::GCWRITEBARRIER, loc, 2,
				    lhs, rhs);
          break;
        }
      // fallthrough

    case Type::TYPE_STRUCT:
      if (type->is_direct_iface_type())
        {
          rhs = Expression::unpack_direct_iface(rhs, loc);
          rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
          call = Runtime::make_call(this, Runtime::GCWRITEBARRIER, loc, 2,
				    lhs, rhs);
        }
      else
        {
          // TODO: split assignments for small struct/array?
          rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
          rhs->unary_expression()->set_does_not_escape();
          call = Runtime::make_call(this, Runtime::TYPEDMEMMOVE, loc, 3,
                                    Expression::make_type_descriptor(type, loc),
                                    lhs, rhs);
        }
      break;
    }

  return this->check_write_barrier(enclosing, assign,
				   Statement::make_statement(call, false));
}

// Return a statement that tests whether write barriers are enabled
// and executes either the efficient code or the write barrier
// function call, depending.

Statement*
Gogo::check_write_barrier(Block* enclosing, Statement* without,
			  Statement* with)
{
  Location loc = without->location();
  Named_object* wb = this->write_barrier_variable();
  // We pretend that writeBarrier is a uint32, so that we do a
  // 32-bit load.  That is what the gc toolchain does.
  Type* void_type = Type::make_void_type();
  Type* unsafe_pointer_type = Type::make_pointer_type(void_type);
  Type* uint32_type = Type::lookup_integer_type("uint32");
  Type* puint32_type = Type::make_pointer_type(uint32_type);
  Expression* ref = Expression::make_var_reference(wb, loc);
  ref = Expression::make_unary(OPERATOR_AND, ref, loc);
  ref = Expression::make_cast(unsafe_pointer_type, ref, loc);
  ref = Expression::make_cast(puint32_type, ref, loc);
  ref = Expression::make_dereference(ref,
                                     Expression::NIL_CHECK_NOT_NEEDED, loc);
  Expression* zero = Expression::make_integer_ul(0, ref->type(), loc);
  Expression* cond = Expression::make_binary(OPERATOR_EQEQ, ref, zero, loc);

  Block* then_block = new Block(enclosing, loc);
  then_block->add_statement(without);

  Block* else_block = new Block(enclosing, loc);
  else_block->add_statement(with);

  Statement* s = Statement::make_if_statement(cond, then_block, else_block,
					      loc);
  s->determine_types(this);
  return s;
}
