compiler: add '$' to names in expression export data

For inlined function bodies we're going to need to refer to variables,
so change the existing export data to add a '$' to names that look
like identifiers: true, false, nil, convert.

While we're here drop an unnecessary space character after operators.

Change-Id: Id6c32963052cf6dafad39a95ebe54c567e2b9481
Reviewed-on: https://go-review.googlesource.com/c/150067
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/go/expressions.cc b/go/expressions.cc
index 9292b5c..c33f669 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -1610,7 +1610,7 @@
 
   void
   do_export(Export_function_body* efb) const
-  { efb->write_c_string(this->val_ ? "true" : "false"); }
+  { efb->write_c_string(this->val_ ? "$true" : "$false"); }
 
   void
   do_dump_expression(Ast_dump_context* ast_dump_context) const
@@ -1651,6 +1651,8 @@
 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");
@@ -3162,7 +3164,7 @@
 
   void
   do_export(Export_function_body* efb) const
-  { efb->write_c_string("nil"); }
+  { efb->write_c_string("$nil"); }
 
   void
   do_dump_expression(Ast_dump_context* ast_dump_context) const
@@ -3174,6 +3176,8 @@
 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);
 }
@@ -3613,7 +3617,7 @@
 void
 Type_conversion_expression::do_export(Export_function_body* efb) const
 {
-  efb->write_c_string("convert(");
+  efb->write_c_string("$convert(");
   efb->write_type(this->type_);
   efb->write_c_string(", ");
   this->expr_->export_expression(efb);
@@ -3625,7 +3629,7 @@
 Expression*
 Type_conversion_expression::do_import(Import_expression* imp, Location loc)
 {
-  imp->require_c_string("convert(");
+  imp->require_c_string("$convert(");
   Type* type = imp->read_type();
   imp->require_c_string(", ");
   Expression* val = Expression::import_expression(imp, loc);
@@ -4612,16 +4616,16 @@
   switch (this->op_)
     {
     case OPERATOR_PLUS:
-      efb->write_c_string("+ ");
+      efb->write_c_string("+");
       break;
     case OPERATOR_MINUS:
-      efb->write_c_string("- ");
+      efb->write_c_string("-");
       break;
     case OPERATOR_NOT:
-      efb->write_c_string("! ");
+      efb->write_c_string("!");
       break;
     case OPERATOR_XOR:
-      efb->write_c_string("^ ");
+      efb->write_c_string("^");
       break;
     case OPERATOR_AND:
     case OPERATOR_MULT:
@@ -4654,7 +4658,8 @@
     default:
       go_unreachable();
     }
-  imp->require_c_string(" ");
+  if (imp->version() < EXPORT_FORMAT_V3)
+    imp->require_c_string(" ");
   Expression* expr = Expression::import_expression(imp, loc);
   return Expression::make_unary(op, expr, loc);
 }
@@ -12959,7 +12964,7 @@
 void
 Struct_construction_expression::do_export(Export_function_body* efb) const
 {
-  efb->write_c_string("convert(");
+  efb->write_c_string("$convert(");
   efb->write_type(this->type_);
   for (Expression_list::const_iterator pv = this->vals()->begin();
        pv != this->vals()->end();
@@ -13192,7 +13197,7 @@
 void
 Array_construction_expression::do_export(Export_function_body* efb) const
 {
-  efb->write_c_string("convert(");
+  efb->write_c_string("$convert(");
   efb->write_type(this->type_);
   if (this->vals() != NULL)
     {
@@ -13709,7 +13714,7 @@
 void
 Map_construction_expression::do_export(Export_function_body* efb) const
 {
-  efb->write_c_string("convert(");
+  efb->write_c_string("$convert(");
   efb->write_type(this->type_);
   for (Expression_list::const_iterator pv = this->vals_->begin();
        pv != this->vals_->end();
@@ -16141,14 +16146,15 @@
 Expression::import_expression(Import_expression* imp, Location loc)
 {
   int c = imp->peek_char();
-  if (imp->match_c_string("- ")
-      || imp->match_c_string("! ")
-      || imp->match_c_string("^ "))
+  if (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"))
+  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);
@@ -16157,9 +16163,13 @@
       // This handles integers, floats and complex constants.
       return Integer_expression::do_import(imp, loc);
     }
-  else if (imp->match_c_string("nil"))
+  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"))
+  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);
   else
     {
diff --git a/go/import.h b/go/import.h
index c2120c9..948cdf7 100644
--- a/go/import.h
+++ b/go/import.h
@@ -71,6 +71,10 @@
   // Read a type.
   virtual Type*
   read_type() = 0;
+
+  // Return the version number of the export data we're reading.
+  virtual Export_data_version
+  version() const = 0;
 };
 
 // This class manages importing Go declarations.
@@ -253,6 +257,10 @@
   advance(size_t skip)
   { this->stream_->advance(skip); }
 
+  // Return the version number of the export data we're reading.
+  Export_data_version
+  version() const { return this->version_; }
+
   // Skip a semicolon if using an older version.
   void
   require_semicolon_if_old_version()
@@ -381,10 +389,6 @@
     return true;
   }
 
-  // Return the version number of the export data we're reading.
-  Export_data_version
-  version() const { return this->version_; }
-
   // The general IR.
   Gogo* gogo_;
   // The stream from which to read import data.
@@ -638,6 +642,10 @@
   Type*
   read_type();
 
+  Export_data_version
+  version() const
+  { return this->imp_->version(); }
+
   // Implement Import_expression.
   Import_function_body*
   ifb()
diff --git a/libgo/go/go/internal/gccgoimporter/parser.go b/libgo/go/go/internal/gccgoimporter/parser.go
index c23002f..6f01010 100644
--- a/libgo/go/go/internal/gccgoimporter/parser.go
+++ b/libgo/go/go/internal/gccgoimporter/parser.go
@@ -282,6 +282,15 @@
 // ConstValue     = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
 // FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
 func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) {
+	// v3 changed to $false, $true, $convert, to avoid confusion
+	// with variable names in inline function bodies.
+	if p.tok == '$' {
+		p.next()
+		if p.tok != scanner.Ident {
+			p.errorf("expected identifer after '$', got %s (%q)", scanner.TokenString(p.tok), p.lit)
+		}
+	}
+
 	switch p.tok {
 	case scanner.String:
 		str := p.parseString()