compiler: change Expression export to use Export_function_body

In preparation for writing expressions to inline function bodies,
change the existing expression export code to use Export_function_body
rather than Export.  Adjust existing expression exporters accordingly.

This is a refactoring that doesn't affect compiler output.

Change-Id: I998dae2b3bdf039b7bea636b1118b1bc2d5106fd
Reviewed-on: https://go-review.googlesource.com/c/150063
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/go/export.cc b/go/export.cc
index a64c7fd..fde2403 100644
--- a/go/export.cc
+++ b/go/export.cc
@@ -936,21 +936,41 @@
   this->write_c_string(buf);
 }
 
-// Export a type.
+// Return the index of a type.
 
-void
-Export::write_type(const Type* type)
+int
+Export::type_index(const Type* type)
 {
   type = type->forwarded();
   Type_refs::const_iterator p = type_refs.find(type);
   go_assert(p != type_refs.end());
   int index = p->second;
   go_assert(index != 0);
+  return index;
+}
+
+// Export a type.
+
+void
+Export::write_type(const Type* type)
+{
+  int index = this->type_index(type);
   char buf[30];
   snprintf(buf, sizeof buf, "<type %d>", index);
   this->write_c_string(buf);
 }
 
+// Export a type to a function body.
+
+void
+Export::write_type_to(const Type* type, Export_function_body* efb)
+{
+  int index = this->type_index(type);
+  char buf[30];
+  snprintf(buf, sizeof buf, "<type %d>", index);
+  efb->write_c_string(buf);
+}
+
 // Export escape note.
 
 void
diff --git a/go/export.h b/go/export.h
index 5751488..3cbf8e1 100644
--- a/go/export.h
+++ b/go/export.h
@@ -12,6 +12,7 @@
 class Go_sha1_helper;
 class Gogo;
 class Named_object;
+class Export_function_body;
 class Import_init;
 class Named_object;
 class Bindings;
@@ -183,6 +184,10 @@
   void
   write_type(const Type*);
 
+  // Write a type to an exported function body.
+  void
+  write_type_to(const Type*, Export_function_body*);
+
   // Write the escape note to the export stream.  If NOTE is NULL, write
   // nothing.
   void
@@ -241,6 +246,10 @@
   void
   register_builtin_type(Gogo*, const char* name, Builtin_code);
 
+  // Return the index of a type in the export data.
+  int
+  type_index(const Type*);
+
   // The stream to which we are writing data.
   Stream* stream_;
   // Index number of next type.
@@ -290,11 +299,11 @@
 // to Statements and Expressions.  It builds up the export data for
 // the function.
 
-class Export_function_body
+class Export_function_body : public String_dump
 {
  public:
-  Export_function_body(int indent)
-    : indent_(indent)
+  Export_function_body(Export* exp, int indent)
+    : exp_(exp), indent_(indent)
   { }
 
   // Write a character to the body.
@@ -312,6 +321,11 @@
   write_string(const std::string& str)
   { this->body_.append(str); }
 
+  // Write a type reference to the body.
+  void
+  write_type(const Type* type)
+  { this->exp_->write_type_to(type, this); }
+
   // Append as many spaces as the current indentation level.
   void
   indent()
@@ -336,6 +350,8 @@
   { return this->body_; }
 
  private:
+  // The overall export data.
+  Export* exp_;
   // The body we are building.
   std::string body_;
   // Current indentation level: the number of spaces before each statement.
diff --git a/go/expressions.cc b/go/expressions.cc
index db7c981..0e2d4fb 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -82,7 +82,7 @@
 // only be used by expressions which may be constant.
 
 void
-Expression::do_export(Export*) const
+Expression::do_export(Export_function_body*) const
 {
   go_unreachable();
 }
@@ -1609,8 +1609,8 @@
   { return context->backend()->boolean_constant_expression(this->val_); }
 
   void
-  do_export(Export* exp) const
-  { exp->write_c_string(this->val_ ? "true" : "false"); }
+  do_export(Export_function_body* efb) const
+  { efb->write_c_string(this->val_ ? "true" : "false"); }
 
   void
   do_dump_expression(Ast_dump_context* ast_dump_context) const
@@ -1760,9 +1760,9 @@
 // Export a string expression.
 
 void
-String_expression::do_export(Export* exp) const
+String_expression::do_export(Export_function_body* efb) const
 {
-  String_expression::export_string(exp, this);
+  String_expression::export_string(efb, this);
 }
 
 // Import a string expression.
@@ -1996,7 +1996,7 @@
   }
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -2138,13 +2138,13 @@
 // Export an integer in a constant expression.
 
 void
-Integer_expression::do_export(Export* exp) const
+Integer_expression::do_export(Export_function_body* efb) const
 {
-  Integer_expression::export_integer(exp, this->val_);
+  Integer_expression::export_integer(efb, this->val_);
   if (this->is_character_constant_)
-    exp->write_c_string("'");
+    efb->write_c_string("'");
   // A trailing space lets us reliably identify the end of the number.
-  exp->write_c_string(" ");
+  efb->write_c_string(" ");
 }
 
 // Import an integer, floating point, or complex value.  This handles
@@ -2393,7 +2393,7 @@
   do_get_backend(Translate_context*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -2505,11 +2505,11 @@
 // Export a floating point number in a constant expression.
 
 void
-Float_expression::do_export(Export* exp) const
+Float_expression::do_export(Export_function_body* efb) const
 {
-  Float_expression::export_float(exp, this->val_);
+  Float_expression::export_float(efb, this->val_);
   // A trailing space lets us reliably identify the end of the number.
-  exp->write_c_string(" ");
+  efb->write_c_string(" ");
 }
 
 // Dump a floating point number to the dump file.
@@ -2588,7 +2588,7 @@
   do_get_backend(Translate_context*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -2695,11 +2695,11 @@
 // Export a complex number in a constant expression.
 
 void
-Complex_expression::do_export(Export* exp) const
+Complex_expression::do_export(Export_function_body* efb) const
 {
-  Complex_expression::export_complex(exp, this->val_);
+  Complex_expression::export_complex(efb, this->val_);
   // A trailing space lets us reliably identify the end of the number.
-  exp->write_c_string(" ");
+  efb->write_c_string(" ");
 }
 
 // Dump a complex expression to the dump file.
@@ -2804,8 +2804,8 @@
   // expression, we export the value.  We ignore the fact that it has
   // a name.
   void
-  do_export(Export* exp) const
-  { this->constant_->const_value()->expr()->export_expression(exp); }
+  do_export(Export_function_body* efb) const
+  { this->constant_->const_value()->expr()->export_expression(efb); }
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -3161,8 +3161,8 @@
   { return context->backend()->nil_pointer_expression(); }
 
   void
-  do_export(Export* exp) const
-  { exp->write_c_string("nil"); }
+  do_export(Export_function_body* efb) const
+  { efb->write_c_string("nil"); }
 
   void
   do_dump_expression(Ast_dump_context* ast_dump_context) const
@@ -3611,13 +3611,13 @@
 // Output a type conversion in a constant expression.
 
 void
-Type_conversion_expression::do_export(Export* exp) const
+Type_conversion_expression::do_export(Export_function_body* efb) const
 {
-  exp->write_c_string("convert(");
-  exp->write_type(this->type_);
-  exp->write_c_string(", ");
-  this->expr_->export_expression(exp);
-  exp->write_c_string(")");
+  efb->write_c_string("convert(");
+  efb->write_type(this->type_);
+  efb->write_c_string(", ");
+  this->expr_->export_expression(efb);
+  efb->write_c_string(")");
 }
 
 // Import a type conversion or a struct construction.
@@ -4607,28 +4607,28 @@
 // Export a unary expression.
 
 void
-Unary_expression::do_export(Export* exp) const
+Unary_expression::do_export(Export_function_body* efb) const
 {
   switch (this->op_)
     {
     case OPERATOR_PLUS:
-      exp->write_c_string("+ ");
+      efb->write_c_string("+ ");
       break;
     case OPERATOR_MINUS:
-      exp->write_c_string("- ");
+      efb->write_c_string("- ");
       break;
     case OPERATOR_NOT:
-      exp->write_c_string("! ");
+      efb->write_c_string("! ");
       break;
     case OPERATOR_XOR:
-      exp->write_c_string("^ ");
+      efb->write_c_string("^ ");
       break;
     case OPERATOR_AND:
     case OPERATOR_MULT:
     default:
       go_unreachable();
     }
-  this->expr_->export_expression(exp);
+  this->expr_->export_expression(efb);
 }
 
 // Import a unary expression.
@@ -6330,74 +6330,74 @@
 // Export a binary expression.
 
 void
-Binary_expression::do_export(Export* exp) const
+Binary_expression::do_export(Export_function_body* efb) const
 {
-  exp->write_c_string("(");
-  this->left_->export_expression(exp);
+  efb->write_c_string("(");
+  this->left_->export_expression(efb);
   switch (this->op_)
     {
     case OPERATOR_OROR:
-      exp->write_c_string(" || ");
+      efb->write_c_string(" || ");
       break;
     case OPERATOR_ANDAND:
-      exp->write_c_string(" && ");
+      efb->write_c_string(" && ");
       break;
     case OPERATOR_EQEQ:
-      exp->write_c_string(" == ");
+      efb->write_c_string(" == ");
       break;
     case OPERATOR_NOTEQ:
-      exp->write_c_string(" != ");
+      efb->write_c_string(" != ");
       break;
     case OPERATOR_LT:
-      exp->write_c_string(" < ");
+      efb->write_c_string(" < ");
       break;
     case OPERATOR_LE:
-      exp->write_c_string(" <= ");
+      efb->write_c_string(" <= ");
       break;
     case OPERATOR_GT:
-      exp->write_c_string(" > ");
+      efb->write_c_string(" > ");
       break;
     case OPERATOR_GE:
-      exp->write_c_string(" >= ");
+      efb->write_c_string(" >= ");
       break;
     case OPERATOR_PLUS:
-      exp->write_c_string(" + ");
+      efb->write_c_string(" + ");
       break;
     case OPERATOR_MINUS:
-      exp->write_c_string(" - ");
+      efb->write_c_string(" - ");
       break;
     case OPERATOR_OR:
-      exp->write_c_string(" | ");
+      efb->write_c_string(" | ");
       break;
     case OPERATOR_XOR:
-      exp->write_c_string(" ^ ");
+      efb->write_c_string(" ^ ");
       break;
     case OPERATOR_MULT:
-      exp->write_c_string(" * ");
+      efb->write_c_string(" * ");
       break;
     case OPERATOR_DIV:
-      exp->write_c_string(" / ");
+      efb->write_c_string(" / ");
       break;
     case OPERATOR_MOD:
-      exp->write_c_string(" % ");
+      efb->write_c_string(" % ");
       break;
     case OPERATOR_LSHIFT:
-      exp->write_c_string(" << ");
+      efb->write_c_string(" << ");
       break;
     case OPERATOR_RSHIFT:
-      exp->write_c_string(" >> ");
+      efb->write_c_string(" >> ");
       break;
     case OPERATOR_AND:
-      exp->write_c_string(" & ");
+      efb->write_c_string(" & ");
       break;
     case OPERATOR_BITCLEAR:
-      exp->write_c_string(" &^ ");
+      efb->write_c_string(" &^ ");
       break;
     default:
       go_unreachable();
     }
-  this->right_->export_expression(exp);
-  exp->write_c_string(")");
+  this->right_->export_expression(efb);
+  efb->write_c_string(")");
 }
 
 // Import a binary expression.
@@ -9454,7 +9454,7 @@
 // code can set a constant to the result of a builtin expression.
 
 void
-Builtin_call_expression::do_export(Export* exp) const
+Builtin_call_expression::do_export(Export_function_body* efb) const
 {
   Numeric_constant nc;
   if (!this->numeric_constant_value(&nc))
@@ -9467,28 +9467,28 @@
     {
       mpz_t val;
       nc.get_int(&val);
-      Integer_expression::export_integer(exp, 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(exp, 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(exp, 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.
-  exp->write_c_string(" ");
+  efb->write_c_string(" ");
 }
 
 // Class Call_expression.
@@ -12957,19 +12957,19 @@
 // Export a struct construction.
 
 void
-Struct_construction_expression::do_export(Export* exp) const
+Struct_construction_expression::do_export(Export_function_body* efb) const
 {
-  exp->write_c_string("convert(");
-  exp->write_type(this->type_);
+  efb->write_c_string("convert(");
+  efb->write_type(this->type_);
   for (Expression_list::const_iterator pv = this->vals()->begin();
        pv != this->vals()->end();
        ++pv)
     {
-      exp->write_c_string(", ");
+      efb->write_c_string(", ");
       if (*pv != NULL)
-	(*pv)->export_expression(exp);
+	(*pv)->export_expression(efb);
     }
-  exp->write_c_string(")");
+  efb->write_c_string(")");
 }
 
 // Dump ast representation of a struct construction expression.
@@ -13190,10 +13190,10 @@
 // Export an array construction.
 
 void
-Array_construction_expression::do_export(Export* exp) const
+Array_construction_expression::do_export(Export_function_body* efb) const
 {
-  exp->write_c_string("convert(");
-  exp->write_type(this->type_);
+  efb->write_c_string("convert(");
+  efb->write_type(this->type_);
   if (this->vals() != NULL)
     {
       std::vector<unsigned long>::const_iterator pi;
@@ -13203,24 +13203,24 @@
 	   pv != this->vals()->end();
 	   ++pv)
 	{
-	  exp->write_c_string(", ");
+	  efb->write_c_string(", ");
 
 	  if (this->indexes_ != NULL)
 	    {
 	      char buf[100];
 	      snprintf(buf, sizeof buf, "%lu", *pi);
-	      exp->write_c_string(buf);
-	      exp->write_c_string(":");
+	      efb->write_c_string(buf);
+	      efb->write_c_string(":");
 	    }
 
 	  if (*pv != NULL)
-	    (*pv)->export_expression(exp);
+	    (*pv)->export_expression(efb);
 
 	  if (this->indexes_ != NULL)
 	    ++pi;
 	}
     }
-  exp->write_c_string(")");
+  efb->write_c_string(")");
 }
 
 // Dump ast representation of an array construction expression.
@@ -13707,18 +13707,18 @@
 // Export an array construction.
 
 void
-Map_construction_expression::do_export(Export* exp) const
+Map_construction_expression::do_export(Export_function_body* efb) const
 {
-  exp->write_c_string("convert(");
-  exp->write_type(this->type_);
+  efb->write_c_string("convert(");
+  efb->write_type(this->type_);
   for (Expression_list::const_iterator pv = this->vals_->begin();
        pv != this->vals_->end();
        ++pv)
     {
-      exp->write_c_string(", ");
-      (*pv)->export_expression(exp);
+      efb->write_c_string(", ");
+      (*pv)->export_expression(efb);
     }
-  exp->write_c_string(")");
+  efb->write_c_string(")");
 }
 
 // Dump ast representation for a map construction expression.
diff --git a/go/expressions.h b/go/expressions.h
index 33ea9b2..9c3122a 100644
--- a/go/expressions.h
+++ b/go/expressions.h
@@ -65,7 +65,7 @@
 class Compound_expression;
 class Numeric_constant;
 class Named_object;
-class Export;
+class Export_function_body;
 class Import;
 class Temporary_statement;
 class Label;
@@ -1009,12 +1009,10 @@
   backend_numeric_constant_expression(Translate_context*,
                                       Numeric_constant* val);
 
-  // Export the expression.  This is only used for constants.  It will
-  // be used for things like values of named constants and sizes of
-  // arrays.
+  // Export the expression.
   void
-  export_expression(Export* exp) const
-  { this->do_export(exp); }
+  export_expression(Export_function_body* efb) const
+  { this->do_export(efb); }
 
   // Import an expression.
   static Expression*
@@ -1130,7 +1128,7 @@
 
   // Child class implements export.
   virtual void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   // For children to call to give an error for an unused value.
   void
@@ -1603,7 +1601,7 @@
   export_string(String_dump* exp, const String_expression* str);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -1687,7 +1685,7 @@
   do_get_backend(Translate_context* context);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -1878,7 +1876,7 @@
   do_get_backend(Translate_context*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -2023,7 +2021,7 @@
   do_get_backend(Translate_context*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -2130,7 +2128,7 @@
   { go_unreachable(); }
 
   void
-  do_export(Export*) const
+  do_export(Export_function_body*) const
   { go_unreachable(); }
 
   void
@@ -2456,7 +2454,7 @@
   do_get_backend(Translate_context*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   virtual bool
   do_is_recover_call() const;
@@ -3551,7 +3549,7 @@
   do_get_backend(Translate_context*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -3606,7 +3604,7 @@
   do_check_types(Gogo*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   // The indexes.
   const std::vector<unsigned long>*
@@ -3744,7 +3742,7 @@
   do_get_backend(Translate_context*);
 
   void
-  do_export(Export*) const;
+  do_export(Export_function_body*) const;
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -3859,7 +3857,7 @@
   // We only export global objects, and the parser does not generate
   // this in global scope.
   void
-  do_export(Export*) const
+  do_export(Export_function_body*) const
   { go_unreachable(); }
 
   void
diff --git a/go/gogo.cc b/go/gogo.cc
index 552de18..cc2c654 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -5572,7 +5572,7 @@
       if (fntype->is_method())
 	indent++;
 
-      Export_function_body efb(indent);
+      Export_function_body efb(exp, indent);
 
       efb.indent();
       efb.write_c_string("// ");
@@ -7606,7 +7606,11 @@
       exp->write_c_string(" ");
     }
   exp->write_c_string("= ");
-  this->expr()->export_expression(exp);
+
+  Export_function_body efb(exp, 0);
+  this->expr()->export_expression(&efb);
+  exp->write_string(efb.body());
+
   exp->write_c_string("\n");
 }
 
diff --git a/go/types.cc b/go/types.cc
index 2750242..d4cf4ed 100644
--- a/go/types.cc
+++ b/go/types.cc
@@ -6566,7 +6566,11 @@
 	  exp->write_c_string(" ");
 	  Expression* expr =
             Expression::make_string(p->tag(), Linemap::predeclared_location());
-	  expr->export_expression(exp);
+
+	  Export_function_body efb(exp, 0);
+	  expr->export_expression(&efb);
+	  exp->write_string(efb.body());
+
 	  delete expr;
 	}
 
@@ -7545,7 +7549,11 @@
 {
   exp->write_c_string("[");
   if (this->length_ != NULL)
-    this->length_->export_expression(exp);
+    {
+      Export_function_body efb(exp, 0);
+      this->length_->export_expression(&efb);
+      exp->write_string(efb.body());
+    }
   exp->write_c_string("] ");
   exp->write_type(this->element_type_);
 }