LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - export.cc (source / functions) Hit Total Coverage
Test: gcc.info Lines: 755 839 90.0 %
Date: 2022-09-24 20:31:59 Functions: 46 49 93.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // export.cc -- Export declarations in Go frontend.
       2                 :            : 
       3                 :            : // Copyright 2009 The Go Authors. All rights reserved.
       4                 :            : // Use of this source code is governed by a BSD-style
       5                 :            : // license that can be found in the LICENSE file.
       6                 :            : 
       7                 :            : #include "go-system.h"
       8                 :            : 
       9                 :            : #include "go-c.h"
      10                 :            : #include "go-diagnostics.h"
      11                 :            : #include "go-sha1.h"
      12                 :            : #include "gogo.h"
      13                 :            : #include "types.h"
      14                 :            : #include "expressions.h"
      15                 :            : #include "statements.h"
      16                 :            : #include "export.h"
      17                 :            : #include "go-linemap.h"
      18                 :            : #include "backend.h"
      19                 :            : 
      20                 :            : // This file handles exporting global declarations.
      21                 :            : 
      22                 :            : // Class Export.
      23                 :            : 
      24                 :            : const int Export::magic_len;
      25                 :            : 
      26                 :            : // Current version magic string.
      27                 :            : const char Export::cur_magic[Export::magic_len] =
      28                 :            :   {
      29                 :            :     'v', '3', ';', '\n'
      30                 :            :   };
      31                 :            : 
      32                 :            : // Magic strings for previous versions (still supported).
      33                 :            : const char Export::v1_magic[Export::magic_len] =
      34                 :            :   {
      35                 :            :     'v', '1', ';', '\n'
      36                 :            :   };
      37                 :            : const char Export::v2_magic[Export::magic_len] =
      38                 :            :   {
      39                 :            :     'v', '2', ';', '\n'
      40                 :            :   };
      41                 :            : 
      42                 :            : const int Export::checksum_len;
      43                 :            : 
      44                 :            : // Type hash table operations, treating aliases as distinct.
      45                 :            : 
      46                 :            : class Type_hash_alias_identical
      47                 :            : {
      48                 :            :  public:
      49                 :            :   unsigned int
      50                 :    2681012 :   operator()(const Type* type) const
      51                 :            :   {
      52                 :    2681012 :     return type->hash_for_method(NULL,
      53                 :            :                                  (Type::COMPARE_ERRORS
      54                 :            :                                   | Type::COMPARE_TAGS
      55                 :            :                                   | Type::COMPARE_EMBEDDED_INTERFACES
      56                 :            :                                   | Type::COMPARE_ALIASES));
      57                 :            :   }
      58                 :            : };
      59                 :            : 
      60                 :            : class Type_alias_identical
      61                 :            : {
      62                 :            :  public:
      63                 :            :   bool
      64                 :    5683963 :   operator()(const Type* t1, const Type* t2) const
      65                 :            :   {
      66                 :    5680838 :     return Type::are_identical(t1, t2,
      67                 :            :                                (Type::COMPARE_ERRORS
      68                 :            :                                 | Type::COMPARE_TAGS
      69                 :            :                                 | Type::COMPARE_EMBEDDED_INTERFACES
      70                 :            :                                 | Type::COMPARE_ALIASES),
      71                 :            :                                NULL);
      72                 :            :   }
      73                 :            : };
      74                 :            : 
      75                 :            : // Mapping from Type objects to a constant index.
      76                 :            : typedef Unordered_map_hash(const Type*, int, Type_hash_alias_identical,
      77                 :            :                            Type_alias_identical) Type_refs;
      78                 :            : 
      79                 :            : // Implementation object for class Export.  Hidden implementation avoids
      80                 :            : // having to #include types.h in export.h, or use a static map.
      81                 :            : 
      82                 :       4251 : struct Export_impl {
      83                 :            :   Type_refs type_refs;
      84                 :            : };
      85                 :            : 
      86                 :            : // Constructor.
      87                 :            : 
      88                 :       4251 : Export::Export(Stream* stream)
      89                 :       4251 :     : stream_(stream), type_index_(1), packages_(), impl_(new Export_impl)
      90                 :            : {
      91                 :       4251 :   go_assert(Export::checksum_len == Go_sha1_helper::checksum_len);
      92                 :       4251 : }
      93                 :            : 
      94                 :            : // Destructor.
      95                 :            : 
      96                 :       4251 : Export::~Export()
      97                 :            : {
      98                 :       8502 :   delete this->impl_;
      99                 :       4251 : }
     100                 :            : 
     101                 :            : // A traversal class to collect functions and global variables
     102                 :            : // referenced by inlined functions, and also to gather up
     103                 :            : // referenced types that need to be included in the exports.
     104                 :            : 
     105                 :            : class Collect_export_references : public Traverse
     106                 :            : {
     107                 :            :  public:
     108                 :       4251 :   Collect_export_references(Export* exp,
     109                 :            :                             const std::map<std::string, Package*>& packages,
     110                 :            :                             Unordered_set(Named_object*)* exports,
     111                 :            :                             Unordered_set(const Package*)* imports)
     112                 :       4251 :     : Traverse(traverse_expressions
     113                 :            :                | traverse_types),
     114                 :       4251 :       exp_(exp), packages_(packages), exports_(exports), imports_(imports),
     115                 :       4251 :       inline_fcn_worklist_(NULL), exports_finalized_(false)
     116                 :            :   { }
     117                 :            : 
     118                 :            :   // Initial entry point; performs a walk to expand the exports set.
     119                 :            :   void
     120                 :            :   expand_exports(std::vector<Named_object*>* inlinable_functions);
     121                 :            : 
     122                 :            :   // Second entry point (called after the method above), to find
     123                 :            :   // all types referenced by exports.
     124                 :            :   void
     125                 :            :   prepare_types(const std::vector<Named_object*>& sorted_exports);
     126                 :            : 
     127                 :            :   // Third entry point (called after the method above), to find
     128                 :            :   // all types in expressions referenced by exports.
     129                 :            :   void
     130                 :            :   prepare_expressions(const std::vector<Named_object*>& sorted_exports);
     131                 :            : 
     132                 :            :  protected:
     133                 :            :   // Override of parent class method.
     134                 :            :   int
     135                 :            :   expression(Expression**);
     136                 :            : 
     137                 :            :   // Override of parent class method.
     138                 :            :   int
     139                 :            :   type(Type* type);
     140                 :            : 
     141                 :            :   // Traverse the components of a function type.
     142                 :            :   void
     143                 :            :   traverse_function_type(Function_type*);
     144                 :            : 
     145                 :            :   // Traverse the methods of a named type, and register its package.
     146                 :            :   void
     147                 :            :   traverse_named_type(Named_type*);
     148                 :            : 
     149                 :            :  private:
     150                 :            : 
     151                 :            :   // Add a named object to the exports set (during expand_exports()).
     152                 :            :   // Returns TRUE if a new object was added to the exports set,
     153                 :            :   // FALSE otherwise.
     154                 :            :   bool
     155                 :            :   add_to_exports(Named_object*);
     156                 :            : 
     157                 :            :   // The exporter.
     158                 :            :   Export* exp_;
     159                 :            :   // The list of packages known to this compilation.
     160                 :            :   const std::map<std::string, Package*>& packages_;
     161                 :            :   // The set of named objects to export.
     162                 :            :   Unordered_set(Named_object*)* exports_;
     163                 :            :   // Set containing all directly and indirectly imported packages.
     164                 :            :   Unordered_set(const Package*)* imports_;
     165                 :            :   // Functions we've already traversed and don't need to visit again.
     166                 :            :   Unordered_set(Named_object*) checked_functions_;
     167                 :            :   // Worklist of functions we are exporting with inline bodies that need
     168                 :            :   // to be checked.
     169                 :            :   std::vector<Named_object*>* inline_fcn_worklist_;
     170                 :            :   // Set to true if expand_exports() has been called and is complete.
     171                 :            :   bool exports_finalized_;
     172                 :            : };
     173                 :            : 
     174                 :            : void
     175                 :       4251 : Collect_export_references::expand_exports(std::vector<Named_object*>* fcns)
     176                 :            : {
     177                 :       4251 :   this->inline_fcn_worklist_ = fcns;
     178                 :      49673 :   while (!this->inline_fcn_worklist_->empty())
     179                 :            :     {
     180                 :      45422 :       Named_object* no = this->inline_fcn_worklist_->back();
     181                 :      45422 :       this->inline_fcn_worklist_->pop_back();
     182                 :      45422 :       std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
     183                 :      45422 :         this->checked_functions_.insert(no);
     184                 :      45422 :       if (ins.second)
     185                 :            :         {
     186                 :            :           // This traversal may add new objects to this->exports_ and new
     187                 :            :           // functions to this->inline_fcn_worklist_.
     188                 :      41230 :           no->func_value()->block()->traverse(this);
     189                 :            :         }
     190                 :            :     }
     191                 :       4251 :   this->inline_fcn_worklist_ = NULL;
     192                 :       4251 :   this->exports_finalized_ = true;
     193                 :       4251 : }
     194                 :            : 
     195                 :            : bool
     196                 :      53668 : Collect_export_references::add_to_exports(Named_object* no)
     197                 :            : {
     198                 :      53668 :   std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
     199                 :      53668 :       this->exports_->insert(no);
     200                 :            :   // If the export list has been finalized, then we should not be
     201                 :            :   // adding anything new to the exports set.
     202                 :      53668 :   go_assert(!this->exports_finalized_ || !ins.second);
     203                 :      53668 :   return ins.second;
     204                 :            : }
     205                 :            : 
     206                 :            : int
     207                 :     613958 : Collect_export_references::expression(Expression** pexpr)
     208                 :            : {
     209                 :     613958 :   const Expression* expr = *pexpr;
     210                 :            : 
     211                 :     613958 :   const Var_expression* ve = expr->var_expression();
     212                 :     613958 :   if (ve != NULL)
     213                 :            :     {
     214                 :     207965 :       Named_object* no = ve->named_object();
     215                 :     207965 :       if (no->is_variable() && no->var_value()->is_global())
     216                 :            :         {
     217                 :      20944 :           const Package* var_package = no->package();
     218                 :      20944 :           if (var_package != NULL)
     219                 :       3489 :             this->imports_->insert(var_package);
     220                 :            : 
     221                 :      20944 :           this->add_to_exports(no);
     222                 :      20944 :           no->var_value()->set_is_referenced_by_inline();
     223                 :            :         }
     224                 :     207965 :       return TRAVERSE_CONTINUE;
     225                 :            :     }
     226                 :            : 
     227                 :     405993 :   const Func_expression* fe = expr->func_expression();
     228                 :     405993 :   if (fe != NULL)
     229                 :            :     {
     230                 :      59214 :       Named_object* no = fe->named_object();
     231                 :            : 
     232                 :      59214 :       const Package* func_package = fe->named_object()->package();
     233                 :      59214 :       if (func_package != NULL)
     234                 :      19044 :         this->imports_->insert(func_package);
     235                 :            : 
     236                 :      59214 :       if (no->is_function_declaration()
     237                 :      59214 :           && no->func_declaration_value()->type()->is_builtin())
     238                 :            :         return TRAVERSE_CONTINUE;
     239                 :            : 
     240                 :      42781 :       if (this->inline_fcn_worklist_ != NULL)
     241                 :            :         {
     242                 :      32724 :           bool added = this->add_to_exports(no);
     243                 :            : 
     244                 :      32724 :           if (no->is_function())
     245                 :      17538 :             no->func_value()->set_is_referenced_by_inline();
     246                 :            : 
     247                 :            :           // If 'added' is false then this object was already in
     248                 :            :           // exports_, in which case it was already added to
     249                 :            :           // check_inline_refs_ the first time we added it to exports_, so
     250                 :            :           // we don't need to add it again.
     251                 :      32724 :           if (added
     252                 :      18203 :               && no->is_function()
     253                 :      39805 :               && no->func_value()->export_for_inlining())
     254                 :       4192 :             this->inline_fcn_worklist_->push_back(no);
     255                 :            :         }
     256                 :            : 
     257                 :      42781 :       return TRAVERSE_CONTINUE;
     258                 :            :     }
     259                 :            : 
     260                 :     346779 :   const Named_object* nco = expr->named_constant();
     261                 :     346779 :   if (nco != 0)
     262                 :            :     {
     263                 :      37109 :       const Named_constant *nc = nco->const_value();
     264                 :      37109 :       Type::traverse(nc->type(), this);
     265                 :      37109 :       return TRAVERSE_CONTINUE;
     266                 :            :     }
     267                 :            : 
     268                 :     309670 :   const Call_expression* call = expr->call_expression();
     269                 :      58780 :   if (call != NULL)
     270                 :            :     {
     271                 :      58780 :       const Builtin_call_expression* bce = call->builtin_call_expression();
     272                 :      16433 :       if (bce != NULL
     273                 :      16433 :           && (bce->code() == Builtin_call_expression::BUILTIN_ADD
     274                 :      16433 :               || bce->code() == Builtin_call_expression::BUILTIN_SLICE))
     275                 :            :         {
     276                 :            :           // This is a reference to unsafe.Add or unsafe.Slice.  Make
     277                 :            :           // sure we list the "unsafe" package in the imports and give
     278                 :            :           // it a package index.
     279                 :          0 :           const std::map<std::string, Package*>::const_iterator p =
     280                 :          0 :             this->packages_.find("unsafe");
     281                 :          0 :           go_assert(p != this->packages_.end());
     282                 :          0 :           this->imports_->insert(p->second);
     283                 :            :         }
     284                 :            :     }
     285                 :            : 
     286                 :            :   return TRAVERSE_CONTINUE;
     287                 :            : }
     288                 :            : 
     289                 :            : // Collect up the set of types mentioned in expressions of things we're exporting,
     290                 :            : // and collect all the packages encountered during type traversal, to make sure
     291                 :            : // we can declare things referered to indirectly (for example, in the body of an
     292                 :            : // exported inline function from another package).
     293                 :            : 
     294                 :            : void
     295                 :       4251 : Collect_export_references::prepare_expressions(const std::vector<Named_object*>& sorted_exports)
     296                 :            : {
     297                 :     110860 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     298                 :     110860 :        p != sorted_exports.end();
     299                 :     110860 :        ++p)
     300                 :            :     {
     301                 :     106609 :       Named_object* no = *p;
     302                 :     106609 :       if (no->classification() == Named_object::NAMED_OBJECT_CONST)
     303                 :            :         {
     304                 :      38505 :           Expression* e = no->const_value()->expr();
     305                 :      38505 :           if (e != NULL)
     306                 :      38505 :             Expression::traverse(&e, this);
     307                 :            :         }
     308                 :            :     }
     309                 :       4251 : }
     310                 :            : 
     311                 :            : // Collect up the set of types mentioned in things we're exporting, and collect
     312                 :            : // all the packages encountered during type traversal, to make sure we can
     313                 :            : // declare things referered to indirectly (for example, in the body of an
     314                 :            : // exported inline function from another package).
     315                 :            : 
     316                 :            : void
     317                 :       4251 : Collect_export_references::prepare_types(const std::vector<Named_object*>& sorted_exports)
     318                 :            : {
     319                 :            :   // Iterate through the exported objects and traverse any types encountered.
     320                 :     110860 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     321                 :     110860 :        p != sorted_exports.end();
     322                 :     110860 :        ++p)
     323                 :            :     {
     324                 :     106609 :       Named_object* no = *p;
     325                 :     106609 :       switch (no->classification())
     326                 :            :         {
     327                 :      38505 :         case Named_object::NAMED_OBJECT_CONST:
     328                 :      38505 :           {
     329                 :      38505 :             Type* t = no->const_value()->type();
     330                 :      38505 :             if (t != NULL && !t->is_abstract())
     331                 :      15583 :               Type::traverse(t, this);
     332                 :            :           }
     333                 :            :           break;
     334                 :            : 
     335                 :      11407 :         case Named_object::NAMED_OBJECT_TYPE:
     336                 :      11407 :           Type::traverse(no->type_value()->real_type(), this);
     337                 :      11407 :           this->traverse_named_type(no->type_value());
     338                 :      11407 :           break;
     339                 :            : 
     340                 :       8444 :         case Named_object::NAMED_OBJECT_VAR:
     341                 :       8444 :           Type::traverse(no->var_value()->type(), this);
     342                 :       8444 :           break;
     343                 :            : 
     344                 :      36544 :         case Named_object::NAMED_OBJECT_FUNC:
     345                 :      36544 :           {
     346                 :      36544 :             Function* fn = no->func_value();
     347                 :      36544 :             this->traverse_function_type(fn->type());
     348                 :      36544 :             if (fn->export_for_inlining())
     349                 :       9450 :               fn->block()->traverse(this);
     350                 :            :           }
     351                 :            :           break;
     352                 :            : 
     353                 :      11709 :         case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
     354                 :      11709 :           this->traverse_function_type(no->func_declaration_value()->type());
     355                 :      11709 :           break;
     356                 :            : 
     357                 :            :         default:
     358                 :            :           // We shouldn't see anything else.  If we do we'll give an
     359                 :            :           // error later when we try to actually export it.
     360                 :            :           break;
     361                 :            :         }
     362                 :            :     }
     363                 :       4251 : }
     364                 :            : 
     365                 :            : // Record referenced type, record package imports, and make sure we traverse
     366                 :            : // methods of named types.
     367                 :            : 
     368                 :            : int
     369                 :    1015102 : Collect_export_references::type(Type* type)
     370                 :            : {
     371                 :            :   // Skip forwarders; don't try to give them a type index.
     372                 :    1237703 :   if (type->forward_declaration_type() != NULL)
     373                 :            :     return TRAVERSE_CONTINUE;
     374                 :            : 
     375                 :            :   // Skip the void type, which we'll see when exporting
     376                 :            :   // unsafe.Pointer.  The void type is not itself exported, because
     377                 :            :   // Pointer_type::do_export checks for it.
     378                 :     765752 :   if (type->is_void_type())
     379                 :            :     return TRAVERSE_SKIP_COMPONENTS;
     380                 :            : 
     381                 :            :   // Skip the nil type, turns up in function bodies.
     382                 :     765072 :   if (type->is_nil_type())
     383                 :            :     return TRAVERSE_SKIP_COMPONENTS;
     384                 :            : 
     385                 :            :   // Skip abstract types.  We should never see these in real code,
     386                 :            :   // only in things like const declarations.
     387                 :     761404 :   if (type->is_abstract())
     388                 :            :     return TRAVERSE_SKIP_COMPONENTS;
     389                 :            : 
     390                 :     705690 :   if (!this->exp_->record_type(type))
     391                 :            :     {
     392                 :            :       // We've already seen this type.
     393                 :            :       return TRAVERSE_SKIP_COMPONENTS;
     394                 :            :     }
     395                 :            : 
     396                 :            :   // At this stage of compilation traversing interface types traverses
     397                 :            :   // the final list of methods, but we export the locally defined
     398                 :            :   // methods.  If there is an embedded interface type we need to make
     399                 :            :   // sure to export that.  Check classification, rather than calling
     400                 :            :   // the interface_type method, because we want to handle named types
     401                 :            :   // below.
     402                 :     236242 :   if (type->classification() == Type::TYPE_INTERFACE)
     403                 :            :     {
     404                 :      13641 :       Interface_type* it = type->interface_type();
     405                 :      13641 :       const Typed_identifier_list* methods = it->local_methods();
     406                 :      13641 :       if (methods != NULL)
     407                 :            :         {
     408                 :      51537 :           for (Typed_identifier_list::const_iterator p = methods->begin();
     409                 :      51537 :                p != methods->end();
     410                 :      51537 :                ++p)
     411                 :            :             {
     412                 :      39979 :               if (p->name().empty())
     413                 :       2716 :                 Type::traverse(p->type(), this);
     414                 :            :               else
     415                 :      74526 :                 this->traverse_function_type(p->type()->function_type());
     416                 :            :             }
     417                 :            :         }
     418                 :      13641 :       return TRAVERSE_SKIP_COMPONENTS;
     419                 :            :     }
     420                 :            : 
     421                 :     222601 :   Named_type* nt = type->named_type();
     422                 :     222601 :   if (nt != NULL)
     423                 :      76772 :     this->traverse_named_type(nt);
     424                 :            : 
     425                 :            :   return TRAVERSE_CONTINUE;
     426                 :            : }
     427                 :            : 
     428                 :            : void
     429                 :      88179 : Collect_export_references::traverse_named_type(Named_type* nt)
     430                 :            : {
     431                 :      88179 :   const Package* package = nt->named_object()->package();
     432                 :      88179 :   if (package != NULL)
     433                 :      62583 :     this->imports_->insert(package);
     434                 :            : 
     435                 :            :   // We have to traverse the methods of named types, because we are
     436                 :            :   // going to export them.  This is not done by ordinary type
     437                 :            :   // traversal.
     438                 :      88179 :   const Bindings* methods = nt->local_methods();
     439                 :      88179 :   if (methods != NULL)
     440                 :            :     {
     441                 :     116892 :       for (Bindings::const_definitions_iterator pm =
     442                 :      46965 :              methods->begin_definitions();
     443                 :     116892 :            pm != methods->end_definitions();
     444                 :     116892 :            ++pm)
     445                 :            :         {
     446                 :      69927 :           Function* fn = (*pm)->func_value();
     447                 :      69927 :           this->traverse_function_type(fn->type());
     448                 :      69927 :           if (fn->export_for_inlining())
     449                 :       9966 :             fn->block()->traverse(this);
     450                 :            :         }
     451                 :            : 
     452                 :     407978 :       for (Bindings::const_declarations_iterator pm =
     453                 :      46965 :              methods->begin_declarations();
     454                 :     407978 :            pm != methods->end_declarations();
     455                 :     407978 :            ++pm)
     456                 :            :         {
     457                 :     361013 :           Named_object* mno = pm->second;
     458                 :     361013 :           if (mno->is_function_declaration())
     459                 :     291086 :             this->traverse_function_type(mno->func_declaration_value()->type());
     460                 :            :         }
     461                 :            :     }
     462                 :      88179 : }
     463                 :            : 
     464                 :            : // Traverse the types in a function type.  We don't need the function
     465                 :            : // type itself, just the receiver, parameter, and result types.
     466                 :            : 
     467                 :            : void
     468                 :     446529 : Collect_export_references::traverse_function_type(Function_type* type)
     469                 :            : {
     470                 :     446529 :   go_assert(type != NULL);
     471                 :     446529 :   if (this->remember_type(type))
     472                 :            :     return;
     473                 :     446529 :   const Typed_identifier* receiver = type->receiver();
     474                 :     446529 :   if (receiver != NULL)
     475                 :     361013 :     Type::traverse(receiver->type(), this);
     476                 :     446529 :   const Typed_identifier_list* parameters = type->parameters();
     477                 :     446529 :   if (parameters != NULL)
     478                 :     226202 :     parameters->traverse(this);
     479                 :     446529 :   const Typed_identifier_list* results = type->results();
     480                 :     446529 :   if (results != NULL)
     481                 :     340925 :     results->traverse(this);
     482                 :            : }
     483                 :            : 
     484                 :            : // Return true if we should export NO.
     485                 :            : 
     486                 :            : static bool
     487                 :     444837 : should_export(Named_object* no)
     488                 :            : {
     489                 :            :   // We only export objects which are locally defined.
     490                 :     444837 :   if (no->package() != NULL)
     491                 :            :     return false;
     492                 :            : 
     493                 :            :   // We don't export packages.
     494                 :     411944 :   if (no->is_package())
     495                 :            :     return false;
     496                 :            : 
     497                 :            :   // We don't export hidden names.
     498                 :     372654 :   if (Gogo::is_hidden_name(no->name()))
     499                 :            :     return false;
     500                 :            : 
     501                 :            :   // We don't export various special functions.
     502                 :     163792 :   if (Gogo::special_name_pos(no->name()) != std::string::npos)
     503                 :            :     return false;
     504                 :            : 
     505                 :            :   // Methods are exported with the type, not here.
     506                 :     115678 :   if (no->is_function()
     507                 :     115678 :       && no->func_value()->type()->is_method())
     508                 :            :     return false;
     509                 :      85001 :   if (no->is_function_declaration()
     510                 :      85001 :       && no->func_declaration_value()->type()->is_method())
     511                 :            :     return false;
     512                 :            : 
     513                 :            :   // Don't export dummy global variables created for initializers when
     514                 :            :   // used with sinks.
     515                 :      85001 :   if (no->is_variable() && no->name()[0] == '_' && no->name()[1] == '.')
     516                 :            :     return false;
     517                 :            : 
     518                 :            :   return true;
     519                 :            : }
     520                 :            : 
     521                 :            : // Compare Typed_identifier_list's.
     522                 :            : 
     523                 :            : static int
     524                 :            : compare_til(const Typed_identifier_list*, const Typed_identifier_list*);
     525                 :            : 
     526                 :            : // A functor to sort Named_object pointers by name.
     527                 :            : 
     528                 :            : struct Sort_bindings
     529                 :            : {
     530                 :            :   bool
     531                 :    1488084 :   operator()(const Named_object* n1, const Named_object* n2) const
     532                 :            :   {
     533                 :    1488084 :     if (n1 == n2)
     534                 :            :       return false;
     535                 :            : 
     536                 :    1488084 :     if (n1->package() != n2->package())
     537                 :            :       {
     538                 :     338007 :         if (n1->package() == NULL)
     539                 :            :           return true;
     540                 :     293691 :         if (n2->package() == NULL)
     541                 :            :           return false;
     542                 :            : 
     543                 :            :         // Make sure we don't see the same pkgpath twice.
     544                 :     266389 :         const std::string& p1(n1->package()->pkgpath());
     545                 :     266389 :         const std::string& p2(n2->package()->pkgpath());
     546                 :     266389 :         go_assert(p1 != p2);
     547                 :            : 
     548                 :     266389 :         return p1 < p2;
     549                 :            :       }
     550                 :            : 
     551                 :    1150077 :     if (n1->name() != n2->name())
     552                 :    1150072 :       return n1->name() < n2->name();
     553                 :            : 
     554                 :            :     // We shouldn't see the same name twice, but it can happen for
     555                 :            :     // nested type names.
     556                 :            : 
     557                 :          5 :     go_assert(n1->is_type() && n2->is_type());
     558                 :            : 
     559                 :          5 :     unsigned int ind1;
     560                 :          5 :     const Named_object* g1 = n1->type_value()->in_function(&ind1);
     561                 :          5 :     unsigned int ind2;
     562                 :          5 :     const Named_object* g2 = n2->type_value()->in_function(&ind2);
     563                 :            : 
     564                 :          5 :     if (g1 == NULL)
     565                 :            :       {
     566                 :          0 :         go_assert(g2 != NULL);
     567                 :            :         return true;
     568                 :            :       }
     569                 :          5 :     else if (g2 == NULL)
     570                 :            :       return false;
     571                 :          5 :     else if (g1 == g2)
     572                 :            :       {
     573                 :          0 :         go_assert(ind1 != ind2);
     574                 :          0 :         return ind1 < ind2;
     575                 :            :       }
     576                 :          5 :     else if ((g1->package() != g2->package()) || (g1->name() != g2->name()))
     577                 :          4 :       return Sort_bindings()(g1, g2);
     578                 :            :     else
     579                 :            :       {
     580                 :            :         // This case can happen if g1 or g2 is a method.
     581                 :          1 :         if (g1 != NULL && g1->func_value()->is_method())
     582                 :            :           {
     583                 :          1 :             const Typed_identifier* r = g1->func_value()->type()->receiver();
     584                 :          1 :             g1 = r->type()->named_type()->named_object();
     585                 :            :           }
     586                 :          1 :         if (g2 != NULL && g2->func_value()->is_method())
     587                 :            :           {
     588                 :          1 :             const Typed_identifier* r = g2->func_value()->type()->receiver();
     589                 :          1 :             g2 = r->type()->named_type()->named_object();
     590                 :            :           }
     591                 :          1 :         return Sort_bindings()(g1, g2);
     592                 :            :       }
     593                 :            :   }
     594                 :            : };
     595                 :            : 
     596                 :            : // A functor to sort types for export.
     597                 :            : 
     598                 :            : struct Sort_types
     599                 :            : {
     600                 :            :   bool
     601                 :    2033207 :   operator()(const Type* t1, const Type* t2) const
     602                 :            :   {
     603                 :    2033207 :     t1 = t1->forwarded();
     604                 :    2033207 :     t2 = t2->forwarded();
     605                 :            : 
     606                 :    2033207 :     const Named_type* nt1 = t1->named_type();
     607                 :    2033207 :     const Named_type* nt2 = t2->named_type();
     608                 :    2033207 :     if (nt1 != NULL)
     609                 :            :       {
     610                 :     640180 :         if (nt2 != NULL)
     611                 :            :           {
     612                 :     493029 :             Sort_bindings sb;
     613                 :     493029 :             return sb(nt1->named_object(), nt2->named_object());
     614                 :            :           }
     615                 :            :         else
     616                 :            :           return true;
     617                 :            :       }
     618                 :    1393027 :     else if (nt2 != NULL)
     619                 :            :       return false;
     620                 :    1313540 :     if (t1->classification() != t2->classification())
     621                 :     453759 :       return t1->classification() < t2->classification();
     622                 :     859781 :     Gogo* gogo = go_get_gogo();
     623                 :     859781 :     Backend_name b1;
     624                 :     859781 :     gogo->type_descriptor_backend_name(t1, NULL, &b1);
     625                 :     859781 :     Backend_name b2;
     626                 :     859781 :     gogo->type_descriptor_backend_name(t2, NULL, &b2);
     627                 :            : 
     628                 :     859781 :     std::string n1 = b1.name();
     629                 :     859781 :     std::string n2 = b2.name();
     630                 :     859781 :     if (n1 != n2)
     631                 :     858304 :       return n1 < n2;
     632                 :            : 
     633                 :            :     // We should never see equal types here.  If we do, we may not
     634                 :            :     // generate an identical output file for identical input.  But the
     635                 :            :     // backend names can be equal because we want to treat aliases
     636                 :            :     // differently while type_descriptor_backend_name does not.  In
     637                 :            :     // that case we need to traverse the type elements.
     638                 :            : 
     639                 :            :     // t1 == t2 in case std::sort compares elements to themselves.
     640                 :       1477 :     if (t1 == t2)
     641                 :            :       return false;
     642                 :            : 
     643                 :       1477 :     Sort_types sort;
     644                 :       1477 :     Type_alias_identical identical;
     645                 :       1477 :     go_assert(!identical(t1, t2));
     646                 :            : 
     647                 :       1477 :     switch (t1->classification())
     648                 :            :       {
     649                 :            :       case Type::TYPE_ERROR:
     650                 :            :         return false;
     651                 :            : 
     652                 :          0 :       case Type::TYPE_VOID:
     653                 :          0 :       case Type::TYPE_BOOLEAN:
     654                 :          0 :       case Type::TYPE_INTEGER:
     655                 :          0 :       case Type::TYPE_FLOAT:
     656                 :          0 :       case Type::TYPE_COMPLEX:
     657                 :          0 :       case Type::TYPE_STRING:
     658                 :          0 :       case Type::TYPE_SINK:
     659                 :          0 :       case Type::TYPE_NIL:
     660                 :          0 :       case Type::TYPE_CALL_MULTIPLE_RESULT:
     661                 :          0 :       case Type::TYPE_NAMED:
     662                 :          0 :       case Type::TYPE_FORWARD:
     663                 :          0 :       default:
     664                 :          0 :         go_unreachable();
     665                 :            : 
     666                 :        127 :       case Type::TYPE_FUNCTION:
     667                 :        127 :         {
     668                 :        127 :           const Function_type* ft1 = t1->function_type();
     669                 :        127 :           const Function_type* ft2 = t2->function_type();
     670                 :        127 :           const Typed_identifier* r1 = ft1->receiver();
     671                 :        127 :           const Typed_identifier* r2 = ft2->receiver();
     672                 :        127 :           if (r1 == NULL)
     673                 :        127 :             go_assert(r2 == NULL);
     674                 :            :           else
     675                 :            :             {
     676                 :          0 :               go_assert(r2 != NULL);
     677                 :          0 :               const Type* rt1 = r1->type()->forwarded();
     678                 :          0 :               const Type* rt2 = r2->type()->forwarded();
     679                 :          0 :               if (!identical(rt1, rt2))
     680                 :          0 :                 return sort(rt1, rt2);
     681                 :            :             }
     682                 :            : 
     683                 :        127 :           const Typed_identifier_list* p1 = ft1->parameters();
     684                 :        127 :           const Typed_identifier_list* p2 = ft2->parameters();
     685                 :        127 :           if (p1 == NULL || p1->empty())
     686                 :          3 :             go_assert(p2 == NULL || p2->empty());
     687                 :            :           else
     688                 :            :             {
     689                 :        124 :               go_assert(p2 != NULL && !p2->empty());
     690                 :        124 :               int i = compare_til(p1, p2);
     691                 :        124 :               if (i < 0)
     692                 :            :                 return false;
     693                 :         66 :               else if (i > 0)
     694                 :            :                 return true;
     695                 :            :             }
     696                 :            : 
     697                 :          3 :           p1 = ft1->results();
     698                 :          3 :           p2 = ft2->results();
     699                 :          3 :           if (p1 == NULL || p1->empty())
     700                 :          0 :             go_assert(p2 == NULL || p2->empty());
     701                 :            :           else
     702                 :            :             {
     703                 :          3 :               go_assert(p2 != NULL && !p2->empty());
     704                 :          3 :               int i = compare_til(p1, p2);
     705                 :          3 :               if (i < 0)
     706                 :            :                 return false;
     707                 :          3 :               else if (i > 0)
     708                 :            :                 return true;
     709                 :            :             }
     710                 :            : 
     711                 :          0 :           go_unreachable();
     712                 :            :         }
     713                 :            : 
     714                 :        173 :       case Type::TYPE_POINTER:
     715                 :        173 :         {
     716                 :        173 :           const Type* p1 = t1->points_to()->forwarded();
     717                 :        173 :           const Type* p2 = t2->points_to()->forwarded();
     718                 :        173 :           go_assert(!identical(p1, p2));
     719                 :        173 :           return sort(p1, p2);
     720                 :            :         }
     721                 :            : 
     722                 :          2 :       case Type::TYPE_STRUCT:
     723                 :          2 :         {
     724                 :          2 :           const Struct_type* s1 = t1->struct_type();
     725                 :          2 :           const Struct_type* s2 = t2->struct_type();
     726                 :          2 :           const Struct_field_list* f1 = s1->fields();
     727                 :          2 :           const Struct_field_list* f2 = s2->fields();
     728                 :          2 :           go_assert(f1 != NULL && f2 != NULL);
     729                 :          2 :           Struct_field_list::const_iterator p1 = f1->begin();
     730                 :          2 :           Struct_field_list::const_iterator p2 = f2->begin();
     731                 :          8 :           for (; p2 != f2->end(); ++p1, ++p2)
     732                 :            :             {
     733                 :          8 :               go_assert(p1 != f1->end());
     734                 :          8 :               go_assert(p1->field_name() == p2->field_name());
     735                 :          8 :               go_assert(p1->is_anonymous() == p2->is_anonymous());
     736                 :          8 :               const Type* ft1 = p1->type()->forwarded();
     737                 :          8 :               const Type* ft2 = p2->type()->forwarded();
     738                 :          8 :               if (!identical(ft1, ft2))
     739                 :          2 :                 return sort(ft1, ft2);
     740                 :            :             }
     741                 :          0 :           go_assert(p1 == f1->end());
     742                 :          0 :           go_unreachable();
     743                 :            :         }
     744                 :            : 
     745                 :       1085 :       case Type::TYPE_ARRAY:
     746                 :       1085 :         {
     747                 :       2170 :           const Type* e1 = t1->array_type()->element_type()->forwarded();
     748                 :       2170 :           const Type* e2 = t2->array_type()->element_type()->forwarded();
     749                 :       1085 :           go_assert(!identical(e1, e2));
     750                 :       1085 :           return sort(e1, e2);
     751                 :            :         }
     752                 :            : 
     753                 :         65 :       case Type::TYPE_MAP:
     754                 :         65 :         {
     755                 :         65 :           const Map_type* m1 = t1->map_type();
     756                 :         65 :           const Map_type* m2 = t2->map_type();
     757                 :         65 :           const Type* k1 = m1->key_type()->forwarded();
     758                 :         65 :           const Type* k2 = m2->key_type()->forwarded();
     759                 :         65 :           if (!identical(k1, k2))
     760                 :          0 :             return sort(k1, k2);
     761                 :         65 :           const Type* v1 = m1->val_type()->forwarded();
     762                 :         65 :           const Type* v2 = m2->val_type()->forwarded();
     763                 :         65 :           go_assert(!identical(v1, v2));
     764                 :         65 :           return sort(v1, v2);
     765                 :            :         }
     766                 :            : 
     767                 :          0 :       case Type::TYPE_CHANNEL:
     768                 :          0 :         {
     769                 :          0 :           const Type* e1 = t1->channel_type()->element_type()->forwarded();
     770                 :          0 :           const Type* e2 = t2->channel_type()->element_type()->forwarded();
     771                 :          0 :           go_assert(!identical(e1, e2));
     772                 :          0 :           return sort(e1, e2);
     773                 :            :         }
     774                 :            : 
     775                 :         25 :       case Type::TYPE_INTERFACE:
     776                 :         25 :         {
     777                 :         25 :           const Interface_type* it1 = t1->interface_type();
     778                 :         25 :           const Interface_type* it2 = t2->interface_type();
     779                 :         25 :           const Typed_identifier_list* m1 = it1->local_methods();
     780                 :         25 :           const Typed_identifier_list* m2 = it2->local_methods();
     781                 :            : 
     782                 :            :           // We know the full method lists are the same, because the
     783                 :            :           // mangled type names were the same, but here we are looking
     784                 :            :           // at the local method lists, which include embedded
     785                 :            :           // interfaces, and we can have an embedded empty interface.
     786                 :         25 :           if (m1 == NULL || m1->empty())
     787                 :            :             {
     788                 :          1 :               go_assert(m2 != NULL && !m2->empty());
     789                 :            :               return true;
     790                 :            :             }
     791                 :         24 :           else if (m2 == NULL || m2->empty())
     792                 :            :             {
     793                 :            :               go_assert(m1 != NULL && !m1->empty());
     794                 :            :               return false;
     795                 :            :             }
     796                 :            : 
     797                 :         24 :           int i = compare_til(m1, m2);
     798                 :         24 :           if (i < 0)
     799                 :            :             return false;
     800                 :          5 :           else if (i > 0)
     801                 :            :             return true;
     802                 :            :           else
     803                 :          0 :             go_unreachable();
     804                 :            :         }
     805                 :            :       }
     806                 :     859781 :   }
     807                 :            : };
     808                 :            : 
     809                 :            : // Compare Typed_identifier_list's with Sort_types, returning -1, 0, +1.
     810                 :            : 
     811                 :            : static int
     812                 :        151 : compare_til(
     813                 :            :     const Typed_identifier_list* til1,
     814                 :            :     const Typed_identifier_list* til2)
     815                 :            : {
     816                 :        151 :   Type_alias_identical identical;
     817                 :        151 :   Sort_types sort;
     818                 :        151 :   Typed_identifier_list::const_iterator p1 = til1->begin();
     819                 :        151 :   Typed_identifier_list::const_iterator p2 = til2->begin();
     820                 :        252 :   for (; p2 != til2->end(); ++p1, ++p2)
     821                 :            :     {
     822                 :        252 :       if (p1 == til1->end())
     823                 :            :         return -1;
     824                 :        252 :       const Type* t1 = p1->type()->forwarded();
     825                 :        252 :       const Type* t2 = p2->type()->forwarded();
     826                 :        252 :       if (!identical(t1, t2))
     827                 :            :         {
     828                 :        151 :           if (sort(t1, t2))
     829                 :            :             return -1;
     830                 :            :           else
     831                 :            :             return +1;
     832                 :            :         }
     833                 :            :     }
     834                 :          0 :   if (p1 != til1->end())
     835                 :            :     return +1;
     836                 :            :   return 0;
     837                 :            : }
     838                 :            : 
     839                 :            : // Export those identifiers marked for exporting.
     840                 :            : 
     841                 :            : void
     842                 :       4251 : Export::export_globals(const std::string& package_name,
     843                 :            :                        const std::string& prefix,
     844                 :            :                        const std::string& pkgpath,
     845                 :            :                        const std::map<std::string, Package*>& packages,
     846                 :            :                        const std::map<std::string, Package*>& imports,
     847                 :            :                        const std::string& import_init_fn,
     848                 :            :                        const Import_init_set& imported_init_fns,
     849                 :            :                        const Bindings* bindings,
     850                 :            :                        Unordered_set(Named_object*)* functions_marked_inline)
     851                 :            : {
     852                 :            :   // If there have been any errors so far, don't try to export
     853                 :            :   // anything.  That way the export code doesn't have to worry about
     854                 :            :   // mismatched types or other confusions.
     855                 :       4251 :   if (saw_errors())
     856                 :          0 :     return;
     857                 :            : 
     858                 :            :   // EXPORTS is the set of objects to export.  CHECK_INLINE_REFS is a
     859                 :            :   // list of exported function with inline bodies that need to be
     860                 :            :   // checked for references to other objects.  Every function on
     861                 :            :   // CHECK_INLINE_REFS is also on EXPORTS.
     862                 :       4251 :   Unordered_set(Named_object*) exports;
     863                 :       4251 :   std::vector<Named_object*> check_inline_refs;
     864                 :       4251 :   check_inline_refs.reserve(functions_marked_inline->size());
     865                 :            : 
     866                 :            :   // Add all functions/methods from the "marked inlined" set to the
     867                 :            :   // CHECK_INLINE_REFS worklist.
     868                 :      45481 :   for (Unordered_set(Named_object*)::const_iterator p = functions_marked_inline->begin();
     869                 :      45481 :        p != functions_marked_inline->end();
     870                 :      45481 :        ++p)
     871                 :      41230 :       check_inline_refs.push_back(*p);
     872                 :            : 
     873                 :       4251 :   for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
     874                 :     445322 :        p != bindings->end_definitions();
     875                 :     445322 :        ++p)
     876                 :            :     {
     877                 :     441071 :       if (should_export(*p))
     878                 :     441071 :         exports.insert(*p);
     879                 :            :     }
     880                 :            : 
     881                 :       4251 :   for (Bindings::const_declarations_iterator p =
     882                 :       4251 :          bindings->begin_declarations();
     883                 :     329640 :        p != bindings->end_declarations();
     884                 :     329640 :        ++p)
     885                 :            :     {
     886                 :            :       // We export a function declaration as it may be implemented in
     887                 :            :       // supporting C code.  We do not export type declarations.
     888                 :     325389 :       if (p->second->is_function_declaration()
     889                 :     325389 :           && should_export(p->second))
     890                 :     325389 :         exports.insert(p->second);
     891                 :            :     }
     892                 :            : 
     893                 :            :   // Track all imported packages mentioned in export data.
     894                 :       4251 :   Unordered_set(const Package*) all_imports;
     895                 :            : 
     896                 :       4251 :   Collect_export_references collect(this, packages, &exports, &all_imports);
     897                 :            : 
     898                 :            :   // Walk the set of inlinable routine bodies collected above. This
     899                 :            :   // can potentially expand the exports set.
     900                 :       4251 :   collect.expand_exports(&check_inline_refs);
     901                 :            : 
     902                 :            :   // Export the symbols in sorted order.  That will reduce cases where
     903                 :            :   // irrelevant changes to the source code affect the exported
     904                 :            :   // interface.
     905                 :       4251 :   std::vector<Named_object*> sorted_exports;
     906                 :       4251 :   sorted_exports.reserve(exports.size());
     907                 :            : 
     908                 :       4251 :   for (Unordered_set(Named_object*)::const_iterator p = exports.begin();
     909                 :     110860 :        p != exports.end();
     910                 :     110860 :        ++p)
     911                 :            :     {
     912                 :     106609 :       sorted_exports.push_back(*p);
     913                 :            : 
     914                 :     106609 :       const Package* pkg = (*p)->package();
     915                 :     106609 :       if (pkg != NULL)
     916                 :     106609 :         all_imports.insert(pkg);
     917                 :            :     }
     918                 :            : 
     919                 :       4251 :   std::sort(sorted_exports.begin(), sorted_exports.end(), Sort_bindings());
     920                 :            : 
     921                 :            :   // Collect up the set of types mentioned in things we're exporting,
     922                 :            :   // and any packages that may be referred to indirectly.
     923                 :       4251 :   collect.prepare_types(sorted_exports);
     924                 :       4251 :   collect.prepare_expressions(sorted_exports);
     925                 :            : 
     926                 :            :   // Assign indexes to all exported types and types referenced by
     927                 :            :   // things we're exporting.  Return value is index of first non-exported
     928                 :            :   // type.
     929                 :       4251 :   int unexported_type_index = this->assign_type_indices(sorted_exports);
     930                 :            : 
     931                 :            :   // Although the export data is readable, at least this version is,
     932                 :            :   // it is conceptually a binary format.  Start with a four byte
     933                 :            :   // version number.
     934                 :       4251 :   this->write_bytes(Export::cur_magic, Export::magic_len);
     935                 :            : 
     936                 :            :   // The package name.
     937                 :       4251 :   this->write_c_string("package ");
     938                 :       4251 :   this->write_string(package_name);
     939                 :       4251 :   this->write_c_string("\n");
     940                 :            : 
     941                 :            :   // The prefix or package path, used for all global symbols.
     942                 :       4251 :   if (prefix.empty())
     943                 :            :     {
     944                 :       3640 :       go_assert(!pkgpath.empty());
     945                 :       3640 :       this->write_c_string("pkgpath ");
     946                 :       3640 :       this->write_string(pkgpath);
     947                 :            :     }
     948                 :            :   else
     949                 :            :     {
     950                 :        611 :       this->write_c_string("prefix ");
     951                 :        611 :       this->write_string(prefix);
     952                 :            :     }
     953                 :       4251 :   this->write_c_string("\n");
     954                 :            : 
     955                 :       4251 :   this->write_packages(packages);
     956                 :            : 
     957                 :       4251 :   this->write_imports(imports, all_imports);
     958                 :            : 
     959                 :       4251 :   this->write_imported_init_fns(package_name, import_init_fn,
     960                 :            :                                 imported_init_fns);
     961                 :            : 
     962                 :            :   // FIXME: It might be clever to add something about the processor
     963                 :            :   // and ABI being used, although ideally any problems in that area
     964                 :            :   // would be caught by the linker.
     965                 :            : 
     966                 :            :   // Write out all the types, both exported and not.
     967                 :       4251 :   this->write_types(unexported_type_index);
     968                 :            : 
     969                 :            :   // Write out the non-type export data.
     970                 :     110860 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     971                 :     110860 :        p != sorted_exports.end();
     972                 :     110860 :        ++p)
     973                 :            :     {
     974                 :     106609 :       if (!(*p)->is_type())
     975                 :      95202 :         (*p)->export_named_object(this);
     976                 :            :     }
     977                 :            : 
     978                 :       4251 :   std::string checksum = this->stream_->checksum();
     979                 :       4251 :   std::string s = "checksum ";
     980                 :       4251 :   for (std::string::const_iterator p = checksum.begin();
     981                 :      89271 :        p != checksum.end();
     982                 :      89271 :        ++p)
     983                 :            :     {
     984                 :      85020 :       unsigned char c = *p;
     985                 :      85020 :       unsigned int dig = c >> 4;
     986                 :      85020 :       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
     987                 :      85020 :       dig = c & 0xf;
     988                 :     170040 :       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
     989                 :            :     }
     990                 :       4251 :   s += "\n";
     991                 :       4251 :   this->stream_->write_checksum(s);
     992                 :      12753 : }
     993                 :            : 
     994                 :            : // Record a type in the "to be indexed" set. Return true if the type
     995                 :            : // was not already in the set, false otherwise.
     996                 :            : 
     997                 :            : bool
     998                 :     717097 : Export::record_type(Type* type)
     999                 :            : {
    1000                 :     717097 :   type = type->forwarded();
    1001                 :     717097 :   std::pair<Type_refs::iterator, bool> ins =
    1002                 :     717097 :     this->impl_->type_refs.insert(std::make_pair(type, 0));
    1003                 :     717097 :   return ins.second;
    1004                 :            : }
    1005                 :            : 
    1006                 :            : // Assign the specified type an index.
    1007                 :            : 
    1008                 :            : void
    1009                 :     239341 : Export::set_type_index(const Type* type)
    1010                 :            : {
    1011                 :     239341 :   type = type->forwarded();
    1012                 :     239341 :   Type_refs::iterator p = this->impl_->type_refs.find(type);
    1013                 :     239341 :   go_assert(p != this->impl_->type_refs.end());
    1014                 :     239341 :   int index = this->type_index_;
    1015                 :     239341 :   ++this->type_index_;
    1016                 :     239341 :   go_assert(p->second == 0);
    1017                 :     239341 :   p->second = index;
    1018                 :     239341 : }
    1019                 :            : 
    1020                 :            : // This helper assigns type indices to all types mentioned directly or
    1021                 :            : // indirectly in the things we're exporting. Actual exported types are given
    1022                 :            : // indices according to where the appear on the sorted exports list; all other
    1023                 :            : // types appear afterwards. Return value is the total number of exported types
    1024                 :            : // plus 1, e.g. the index of the 1st non-exported type.
    1025                 :            : 
    1026                 :            : int
    1027                 :       4251 : Export::assign_type_indices(const std::vector<Named_object*>& sorted_exports)
    1028                 :            : {
    1029                 :            :   // Assign indexes to all the exported types.
    1030                 :     110860 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
    1031                 :     110860 :        p != sorted_exports.end();
    1032                 :     110860 :        ++p)
    1033                 :            :     {
    1034                 :     106609 :       if (!(*p)->is_type())
    1035                 :      95202 :         continue;
    1036                 :      11407 :       this->record_type((*p)->type_value());
    1037                 :      11407 :       this->set_type_index((*p)->type_value());
    1038                 :            :     }
    1039                 :       4251 :   int ret = this->type_index_;
    1040                 :            : 
    1041                 :            :   // Collect export-referenced, non-builtin types.
    1042                 :       4251 :   std::vector<const Type*> types;
    1043                 :       4251 :   types.reserve(this->impl_->type_refs.size());
    1044                 :     392377 :   for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
    1045                 :     392377 :        p != this->impl_->type_refs.end();
    1046                 :     392377 :        ++p)
    1047                 :            :     {
    1048                 :     388126 :       const Type* t = p->first;
    1049                 :     388126 :       if (p->second != 0)
    1050                 :     160192 :         continue;
    1051                 :     227934 :       types.push_back(t);
    1052                 :            :     }
    1053                 :            : 
    1054                 :            :   // Sort the types.
    1055                 :       4251 :   std::sort(types.begin(), types.end(), Sort_types());
    1056                 :            : 
    1057                 :            :   // Assign numbers to the sorted list.
    1058                 :     232185 :   for (std::vector<const Type *>::const_iterator p = types.begin();
    1059                 :     232185 :        p != types.end();
    1060                 :     232185 :        ++p)
    1061                 :     227934 :     this->set_type_index((*p));
    1062                 :            : 
    1063                 :       4251 :   return ret;
    1064                 :       4251 : }
    1065                 :            : 
    1066                 :            : // Sort packages.
    1067                 :            : 
    1068                 :            : static bool
    1069                 :      13779 : packages_compare(const Package* a, const Package* b)
    1070                 :            : {
    1071                 :      13779 :   if (a->package_name() < b->package_name())
    1072                 :            :     return true;
    1073                 :       7571 :   else if (a->package_name() > b->package_name())
    1074                 :            :     return false;
    1075                 :            : 
    1076                 :         10 :   if (a->pkgpath() < b->pkgpath())
    1077                 :            :     return true;
    1078                 :          8 :   else if (a->pkgpath() > b->pkgpath())
    1079                 :            :     return false;
    1080                 :            : 
    1081                 :            :   // In principle if we get here then a == b.  Try to do something sensible
    1082                 :            :   // even if the import information is inconsistent.
    1083                 :          0 :   if (a->pkgpath_symbol() < b->pkgpath_symbol())
    1084                 :            :     return true;
    1085                 :          0 :   else if (a->pkgpath_symbol() > b->pkgpath_symbol())
    1086                 :            :     return false;
    1087                 :            : 
    1088                 :          0 :   return a < b;
    1089                 :            : }
    1090                 :            : 
    1091                 :            : // Write out all the known packages whose pkgpath symbol is not a
    1092                 :            : // simple transformation of the pkgpath, so that the importing code
    1093                 :            : // can reliably know it.
    1094                 :            : 
    1095                 :            : void
    1096                 :       4251 : Export::write_packages(const std::map<std::string, Package*>& packages)
    1097                 :            : {
    1098                 :            :   // Sort for consistent output.
    1099                 :       4251 :   std::vector<Package*> out;
    1100                 :     116739 :   for (std::map<std::string, Package*>::const_iterator p = packages.begin();
    1101                 :     116739 :        p != packages.end();
    1102                 :     116739 :        ++p)
    1103                 :            :     {
    1104                 :     112488 :       if (p->second->pkgpath_symbol()
    1105                 :     224976 :           != Gogo::pkgpath_for_symbol(p->second->pkgpath()))
    1106                 :        793 :         out.push_back(p->second);
    1107                 :            :     }
    1108                 :            : 
    1109                 :       4251 :   std::sort(out.begin(), out.end(), packages_compare);
    1110                 :            : 
    1111                 :       5044 :   for (std::vector<Package*>::const_iterator p = out.begin();
    1112                 :       5044 :        p != out.end();
    1113                 :       5044 :        ++p)
    1114                 :            :     {
    1115                 :        793 :       this->write_c_string("package ");
    1116                 :        793 :       this->write_string((*p)->package_name());
    1117                 :        793 :       this->write_c_string(" ");
    1118                 :        793 :       this->write_string((*p)->pkgpath());
    1119                 :        793 :       this->write_c_string(" ");
    1120                 :        793 :       this->write_string((*p)->pkgpath_symbol());
    1121                 :        793 :       this->write_c_string("\n");
    1122                 :            :     }
    1123                 :       4251 : }
    1124                 :            : 
    1125                 :            : // Sort imported packages.
    1126                 :            : 
    1127                 :            : static bool
    1128                 :      48627 : import_compare(const std::pair<std::string, Package*>& a,
    1129                 :            :                const std::pair<std::string, Package*>& b)
    1130                 :            : {
    1131                 :      48627 :   return a.first < b.first;
    1132                 :            : }
    1133                 :            : 
    1134                 :            : // Write out the imported packages.
    1135                 :            : 
    1136                 :            : void
    1137                 :       4251 : Export::write_imports(const std::map<std::string, Package*>& imports,
    1138                 :            :                       const Unordered_set(const Package*)& all_imports)
    1139                 :            : {
    1140                 :            :   // Sort the imports for more consistent output.
    1141                 :       4251 :   Unordered_set(const Package*) seen;
    1142                 :       4251 :   std::vector<std::pair<std::string, Package*> > sorted_imports;
    1143                 :       4251 :   for (std::map<std::string, Package*>::const_iterator p = imports.begin();
    1144                 :      26072 :        p != imports.end();
    1145                 :      26072 :        ++p)
    1146                 :            :     {
    1147                 :      21821 :       sorted_imports.push_back(std::make_pair(p->first, p->second));
    1148                 :      21821 :       seen.insert(p->second);
    1149                 :            :     }
    1150                 :            : 
    1151                 :       4251 :   std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare);
    1152                 :            : 
    1153                 :       4251 :   int package_index = 1;
    1154                 :       4251 :   for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
    1155                 :       4251 :          sorted_imports.begin();
    1156                 :      26072 :        p != sorted_imports.end();
    1157                 :      26072 :        ++p)
    1158                 :            :     {
    1159                 :      21821 :       this->write_c_string("import ");
    1160                 :      21821 :       this->write_string(p->second->package_name());
    1161                 :      21821 :       this->write_c_string(" ");
    1162                 :      21821 :       this->write_string(p->second->pkgpath());
    1163                 :      21821 :       this->write_c_string(" \"");
    1164                 :      21821 :       this->write_string(p->first);
    1165                 :      21821 :       this->write_c_string("\"\n");
    1166                 :            : 
    1167                 :      21821 :       this->packages_[p->second] = package_index;
    1168                 :      21821 :       package_index++;
    1169                 :            :     }
    1170                 :            : 
    1171                 :            :   // Write out a separate list of indirectly imported packages.
    1172                 :       4251 :   std::vector<const Package*> indirect_imports;
    1173                 :      20578 :   for (Unordered_set(const Package*)::const_iterator p =
    1174                 :       4251 :          all_imports.begin();
    1175                 :      20578 :        p != all_imports.end();
    1176                 :      20578 :        ++p)
    1177                 :            :     {
    1178                 :      16327 :       if (seen.find(*p) == seen.end())
    1179                 :       6384 :         indirect_imports.push_back(*p);
    1180                 :            :     }
    1181                 :            : 
    1182                 :       4251 :   std::sort(indirect_imports.begin(), indirect_imports.end(),
    1183                 :            :             packages_compare);
    1184                 :            : 
    1185                 :       4251 :   for (std::vector<const Package*>::const_iterator p =
    1186                 :       4251 :          indirect_imports.begin();
    1187                 :      10635 :        p != indirect_imports.end();
    1188                 :      10635 :        ++p)
    1189                 :            :     {
    1190                 :       6384 :       this->write_c_string("indirectimport ");
    1191                 :       6384 :       this->write_string((*p)->package_name());
    1192                 :       6384 :       this->write_c_string(" ");
    1193                 :       6384 :       this->write_string((*p)->pkgpath());
    1194                 :       6384 :       this->write_c_string("\n");
    1195                 :            : 
    1196                 :       6384 :       this->packages_[*p] = package_index;
    1197                 :       6384 :       package_index++;
    1198                 :            :     }
    1199                 :       4251 : }
    1200                 :            : 
    1201                 :            : void
    1202                 :    1267633 : Export::add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink)
    1203                 :            : {
    1204                 :    1267633 :   Init_graph::iterator it = init_graph->find(src);
    1205                 :    1267633 :   if (it != init_graph->end())
    1206                 :    1177962 :     it->second.insert(sink);
    1207                 :            :   else
    1208                 :            :     {
    1209                 :      89671 :       std::set<unsigned> succs;
    1210                 :      89671 :       succs.insert(sink);
    1211                 :      89671 :       (*init_graph)[src] = succs;
    1212                 :      89671 :     }
    1213                 :    1267633 : }
    1214                 :            : 
    1215                 :            : // Constructs the imported portion of the init graph, e.g. those
    1216                 :            : // edges that we read from imported packages.
    1217                 :            : 
    1218                 :            : void
    1219                 :       3547 : Export::populate_init_graph(Init_graph* init_graph,
    1220                 :            :                             const Import_init_set& imported_init_fns,
    1221                 :            :                             const std::map<std::string, unsigned>& init_idx)
    1222                 :            : {
    1223                 :     162074 :   for (Import_init_set::const_iterator p = imported_init_fns.begin();
    1224                 :     162074 :        p != imported_init_fns.end();
    1225                 :     162074 :        ++p)
    1226                 :            :     {
    1227                 :     158527 :       const Import_init* ii = *p;
    1228                 :     158527 :       if (ii->is_dummy())
    1229                 :      64513 :         continue;
    1230                 :      94014 :       std::map<std::string, unsigned>::const_iterator srcit =
    1231                 :      94014 :           init_idx.find(ii->init_name());
    1232                 :      94014 :       go_assert(srcit != init_idx.end());
    1233                 :      94014 :       unsigned src = srcit->second;
    1234                 :    1312422 :       for (std::set<std::string>::const_iterator pci = ii->precursors().begin();
    1235                 :    1312422 :            pci != ii->precursors().end();
    1236                 :    1312422 :            ++pci)
    1237                 :            :         {
    1238                 :    1218408 :           std::map<std::string, unsigned>::const_iterator it =
    1239                 :    1218408 :               init_idx.find(*pci);
    1240                 :    1218408 :           go_assert(it != init_idx.end());
    1241                 :    1218408 :           unsigned sink = it->second;
    1242                 :    1218408 :           add_init_graph_edge(init_graph, src, sink);
    1243                 :            :         }
    1244                 :            :     }
    1245                 :       3547 : }
    1246                 :            : 
    1247                 :            : // Write out the initialization functions which need to run for this
    1248                 :            : // package.
    1249                 :            : 
    1250                 :            : void
    1251                 :       4251 : Export::write_imported_init_fns(const std::string& package_name,
    1252                 :            :                                 const std::string& import_init_fn,
    1253                 :            :                                 const Import_init_set& imported_init_fns)
    1254                 :            : {
    1255                 :       4251 :   if (import_init_fn.empty() && imported_init_fns.empty()) return;
    1256                 :            : 
    1257                 :            :   // Maps a given init function to the its index in the exported "init" clause.
    1258                 :       4241 :   std::map<std::string, unsigned> init_idx;
    1259                 :            : 
    1260                 :       4241 :   this->write_c_string("init");
    1261                 :            : 
    1262                 :       4241 :   if (!import_init_fn.empty())
    1263                 :            :     {
    1264                 :       2617 :       this->write_c_string(" ");
    1265                 :       2617 :       this->write_string(package_name);
    1266                 :       2617 :       this->write_c_string(" ");
    1267                 :       2617 :       this->write_string(import_init_fn);
    1268                 :       2617 :       init_idx[import_init_fn] = 0;
    1269                 :            :     }
    1270                 :            : 
    1271                 :       4241 :   if (imported_init_fns.empty())
    1272                 :            :     {
    1273                 :        694 :       this->write_c_string("\n");
    1274                 :        694 :       return;
    1275                 :            :     }
    1276                 :            : 
    1277                 :       3547 :   typedef std::map<int, std::vector<std::string> > level_map;
    1278                 :       3547 :   Init_graph init_graph;
    1279                 :       3547 :   level_map inits_at_level;
    1280                 :            : 
    1281                 :            :   // Walk through the set of import inits (already sorted by
    1282                 :            :   // init fcn name) and write them out to the exports.
    1283                 :     162074 :   for (Import_init_set::const_iterator p = imported_init_fns.begin();
    1284                 :     162074 :        p != imported_init_fns.end();
    1285                 :     162074 :        ++p)
    1286                 :            :     {
    1287                 :     158527 :       const Import_init* ii = *p;
    1288                 :            : 
    1289                 :     158527 :       if (ii->init_name() == import_init_fn)
    1290                 :          0 :         continue;
    1291                 :            : 
    1292                 :     158527 :       this->write_c_string(" ");
    1293                 :     158527 :       this->write_string(ii->package_name());
    1294                 :     158527 :       this->write_c_string(" ");
    1295                 :     158527 :       this->write_string(ii->init_name());
    1296                 :            : 
    1297                 :            :       // Populate init_idx.
    1298                 :     158527 :       go_assert(init_idx.find(ii->init_name()) == init_idx.end());
    1299                 :     158527 :       unsigned idx = init_idx.size();
    1300                 :     158527 :       init_idx[ii->init_name()] = idx;
    1301                 :            : 
    1302                 :            :       // If the init function has a non-negative priority value, this
    1303                 :            :       // is an indication that it was referred to in an older version
    1304                 :            :       // export data section (e.g. we read a legacy object
    1305                 :            :       // file). Record such init fcns so that we can fix up the graph
    1306                 :            :       // for them (handled later in this function).
    1307                 :     158527 :       if (ii->priority() > 0)
    1308                 :            :         {
    1309                 :          0 :           level_map::iterator it = inits_at_level.find(ii->priority());
    1310                 :          0 :           if (it == inits_at_level.end())
    1311                 :            :             {
    1312                 :          0 :               std::vector<std::string> l;
    1313                 :          0 :               l.push_back(ii->init_name());
    1314                 :          0 :               inits_at_level[ii->priority()] = l;
    1315                 :          0 :             }
    1316                 :            :           else
    1317                 :          0 :             it->second.push_back(ii->init_name());
    1318                 :            :         }
    1319                 :            :     }
    1320                 :       3547 :   this->write_c_string("\n");
    1321                 :            : 
    1322                 :            :   // Create the init graph. Start by populating the graph with
    1323                 :            :   // all the edges we inherited from imported packages.
    1324                 :       3547 :   populate_init_graph(&init_graph, imported_init_fns, init_idx);
    1325                 :            : 
    1326                 :            :   // Now add edges from the local init function to each of the
    1327                 :            :   // imported fcns.
    1328                 :       3547 :   if (!import_init_fn.empty() && import_init_fn[0] != '~')
    1329                 :            :     {
    1330                 :       1403 :       unsigned src = 0;
    1331                 :       1403 :       go_assert(init_idx[import_init_fn] == 0);
    1332                 :      82137 :       for (Import_init_set::const_iterator p = imported_init_fns.begin();
    1333                 :      82137 :            p != imported_init_fns.end();
    1334                 :      82137 :            ++p)
    1335                 :            :         {
    1336                 :      80734 :           const Import_init* ii = *p;
    1337                 :      80734 :           if (ii->is_dummy())
    1338                 :      31509 :             continue;
    1339                 :      49225 :           unsigned sink = init_idx[ii->init_name()];
    1340                 :      49225 :           add_init_graph_edge(&init_graph, src, sink);
    1341                 :            :         }
    1342                 :            :     }
    1343                 :            : 
    1344                 :            :   // In the scenario where one or more of the packages we imported
    1345                 :            :   // was written with the legacy export data format, add dummy edges
    1346                 :            :   // to capture the priority relationships. Here is a package import
    1347                 :            :   // graph as an example:
    1348                 :            :   //
    1349                 :            :   //       *A
    1350                 :            :   //       /|
    1351                 :            :   //      / |
    1352                 :            :   //     B  *C
    1353                 :            :   //       /|
    1354                 :            :   //      / |
    1355                 :            :   //    *D *E
    1356                 :            :   //     | /|
    1357                 :            :   //     |/ |
    1358                 :            :   //    *F  *G
    1359                 :            :   //
    1360                 :            :   // Let's suppose that the object for package "C" is from an old
    1361                 :            :   // gccgo, e.g. it has the old export data format. All other
    1362                 :            :   // packages are compiled with the new compiler and have the new
    1363                 :            :   // format. Packages with *'s have init functions. The scenario is
    1364                 :            :   // that we're compiling a package "A"; during this process we'll
    1365                 :            :   // read the export data for "C". It should look something like
    1366                 :            :   //
    1367                 :            :   //   init F F..import 1 G G..import 1 D D..import 2 E E..import 2;
    1368                 :            :   //
    1369                 :            :   // To capture this information and convey it to the consumers of
    1370                 :            :   // "A", the code below adds edges to the graph from each priority K
    1371                 :            :   // function to every priority K-1 function for appropriate values
    1372                 :            :   // of K. This will potentially add more edges than we need (for
    1373                 :            :   // example, an edge from D to G), but given that we don't expect
    1374                 :            :   // to see large numbers of old objects, this will hopefully be OK.
    1375                 :            : 
    1376                 :       3547 :   if (inits_at_level.size() > 0)
    1377                 :            :     {
    1378                 :          0 :       for (level_map::reverse_iterator it = inits_at_level.rbegin();
    1379                 :          0 :            it != inits_at_level.rend(); ++it)
    1380                 :            :         {
    1381                 :          0 :           int level = it->first;
    1382                 :          0 :           if (level < 2) break;
    1383                 :          0 :           const std::vector<std::string>& fcns_at_level = it->second;
    1384                 :          0 :           for (std::vector<std::string>::const_iterator sit =
    1385                 :          0 :                    fcns_at_level.begin();
    1386                 :          0 :                sit != fcns_at_level.end(); ++sit)
    1387                 :            :             {
    1388                 :          0 :               unsigned src = init_idx[*sit];
    1389                 :          0 :               level_map::iterator it2 = inits_at_level.find(level - 1);
    1390                 :          0 :               if (it2 != inits_at_level.end())
    1391                 :            :                 {
    1392                 :          0 :                   const std::vector<std::string> fcns_at_lm1 = it2->second;
    1393                 :          0 :                   for (std::vector<std::string>::const_iterator mit =
    1394                 :          0 :                            fcns_at_lm1.begin();
    1395                 :          0 :                        mit != fcns_at_lm1.end(); ++mit)
    1396                 :            :                     {
    1397                 :          0 :                       unsigned sink = init_idx[*mit];
    1398                 :          0 :                       add_init_graph_edge(&init_graph, src, sink);
    1399                 :            :                     }
    1400                 :          0 :                 }
    1401                 :            :             }
    1402                 :            :         }
    1403                 :            :     }
    1404                 :            : 
    1405                 :            :   // Write out the resulting graph.
    1406                 :       3547 :   this->write_c_string("init_graph");
    1407                 :      93218 :   for (Init_graph::const_iterator ki = init_graph.begin();
    1408                 :      93218 :        ki != init_graph.end(); ++ki)
    1409                 :            :     {
    1410                 :      89671 :       unsigned src = ki->first;
    1411                 :      89671 :       const std::set<unsigned>& successors = ki->second;
    1412                 :    1357304 :       for (std::set<unsigned>::const_iterator vi = successors.begin();
    1413                 :    1357304 :            vi != successors.end(); ++vi)
    1414                 :            :         {
    1415                 :    1267633 :           this->write_c_string(" ");
    1416                 :    1267633 :           this->write_unsigned(src);
    1417                 :    1267633 :           unsigned sink = (*vi);
    1418                 :    1267633 :           this->write_c_string(" ");
    1419                 :    1267633 :           this->write_unsigned(sink);
    1420                 :            :         }
    1421                 :            :     }
    1422                 :       3547 :   this->write_c_string("\n");
    1423                 :       4251 : }
    1424                 :            : 
    1425                 :            : // Write the types to the export stream.
    1426                 :            : 
    1427                 :            : void
    1428                 :       4251 : Export::write_types(int unexported_type_index)
    1429                 :            : {
    1430                 :            :   // Map from type index to type.
    1431                 :       4251 :   std::vector<const Type*> types(static_cast<size_t>(this->type_index_));
    1432                 :     392377 :   for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
    1433                 :     392377 :        p != this->impl_->type_refs.end();
    1434                 :     392377 :        ++p)
    1435                 :            :     {
    1436                 :     388126 :       if (p->second >= 0)
    1437                 :     239341 :         types.at(p->second) = p->first;
    1438                 :            :     }
    1439                 :            : 
    1440                 :            :   // Write the type information to a buffer.
    1441                 :       4251 :   Stream_to_string type_data;
    1442                 :       4251 :   Export::Stream* orig_stream = this->stream_;
    1443                 :       4251 :   this->stream_ = &type_data;
    1444                 :            : 
    1445                 :       4251 :   std::vector<size_t> type_sizes(static_cast<size_t>(this->type_index_));
    1446                 :       4251 :   type_sizes[0] = 0;
    1447                 :            : 
    1448                 :            :   // Start at 1 because type index 0 is not used.
    1449                 :       4251 :   size_t start_size = 0;
    1450                 :     243592 :   for (int i = 1; i < this->type_index_; ++i)
    1451                 :            :     {
    1452                 :     239341 :       this->write_type_definition(types[i], i);
    1453                 :            : 
    1454                 :     239341 :       size_t cur_size = type_data.string().size();
    1455                 :     239341 :       type_sizes[i] = cur_size - start_size;
    1456                 :     239341 :       start_size = cur_size;
    1457                 :            :     }
    1458                 :            : 
    1459                 :            :   // Back to original stream.
    1460                 :       4251 :   this->stream_ = orig_stream;
    1461                 :            : 
    1462                 :            :   // The line "types MAXP1 EXPORTEDP1 SIZES..." appears before the
    1463                 :            :   // types.  MAXP1 is one more than the maximum type index used; that
    1464                 :            :   // is, it is the size of the array we need to allocate to hold all
    1465                 :            :   // the values.  Indexes 1 up to but not including EXPORTEDP1 are the
    1466                 :            :   // exported types.  The other types are not exported.  SIZES... is a
    1467                 :            :   // list of MAXP1-1 entries listing the size of the type definition
    1468                 :            :   // for each type, starting at index 1.
    1469                 :       4251 :   char buf[100];
    1470                 :       4251 :   snprintf(buf, sizeof buf, "types %d %d", this->type_index_,
    1471                 :            :            unexported_type_index);
    1472                 :       4251 :   this->write_c_string(buf);
    1473                 :            : 
    1474                 :            :   // Start at 1 because type index 0 is not used.
    1475                 :     243592 :   for (int i = 1; i < this->type_index_; ++i)
    1476                 :            :     {
    1477                 :     239341 :       snprintf(buf, sizeof buf, " %lu",
    1478                 :     239341 :                static_cast<unsigned long>(type_sizes[i]));
    1479                 :     239341 :       this->write_c_string(buf);
    1480                 :            :     }
    1481                 :       4251 :   this->write_c_string("\n");
    1482                 :       4251 :   this->write_string(type_data.string());
    1483                 :       4251 : }
    1484                 :            : 
    1485                 :            : // Write a single type to the export stream.
    1486                 :            : 
    1487                 :            : void
    1488                 :     239341 : Export::write_type_definition(const Type* type, int index)
    1489                 :            : {
    1490                 :     239341 :   this->write_c_string("type ");
    1491                 :            : 
    1492                 :     239341 :   char buf[30];
    1493                 :     239341 :   snprintf(buf, sizeof buf, "%d ", index);
    1494                 :     239341 :   this->write_c_string(buf);
    1495                 :            : 
    1496                 :     239341 :   const Named_type* nt = type->named_type();
    1497                 :     239341 :   if (nt != NULL)
    1498                 :            :     {
    1499                 :      79871 :       const Named_object* no = nt->named_object();
    1500                 :      79871 :       const Package* package = no->package();
    1501                 :            : 
    1502                 :      79871 :       this->write_c_string("\"");
    1503                 :      79871 :       if (package != NULL && !Gogo::is_hidden_name(no->name()))
    1504                 :            :         {
    1505                 :      46027 :           this->write_string(package->pkgpath());
    1506                 :      46027 :           this->write_c_string(".");
    1507                 :            :         }
    1508                 :      79871 :       this->write_string(nt->named_object()->name());
    1509                 :      79871 :       this->write_c_string("\" ");
    1510                 :            : 
    1511                 :      79871 :       if (!nt->in_heap())
    1512                 :        509 :         this->write_c_string("notinheap ");
    1513                 :            : 
    1514                 :      79871 :       if (nt->is_alias())
    1515                 :       4780 :         this->write_c_string("= ");
    1516                 :            :     }
    1517                 :            : 
    1518                 :     239341 :   type->export_type(this);
    1519                 :            : 
    1520                 :            :   // Type::export_type will print a newline for a named type, but not
    1521                 :            :   // otherwise.
    1522                 :     239341 :   if (nt == NULL)
    1523                 :     159470 :     this->write_c_string("\n");
    1524                 :     239341 : }
    1525                 :            : 
    1526                 :            : // Write a name to the export stream.
    1527                 :            : 
    1528                 :            : void
    1529                 :     857734 : Export::write_name(const std::string& name)
    1530                 :            : {
    1531                 :     857734 :   if (name.empty())
    1532                 :     102492 :     this->write_c_string("?");
    1533                 :            :   else
    1534                 :     755242 :     this->write_string(Gogo::unpack_hidden_name(name));
    1535                 :     857734 : }
    1536                 :            : 
    1537                 :            : // Write an integer value to the export stream.
    1538                 :            : 
    1539                 :            : void
    1540                 :          0 : Export::write_int(int value)
    1541                 :            : {
    1542                 :          0 :   char buf[100];
    1543                 :          0 :   snprintf(buf, sizeof buf, "%d", value);
    1544                 :          0 :   this->write_c_string(buf);
    1545                 :          0 : }
    1546                 :            : 
    1547                 :            : // Write an integer value to the export stream.
    1548                 :            : 
    1549                 :            : void
    1550                 :    2535266 : Export::write_unsigned(unsigned value)
    1551                 :            : {
    1552                 :    2535266 :   char buf[100];
    1553                 :    2535266 :   snprintf(buf, sizeof buf, "%u", value);
    1554                 :    2535266 :   this->write_c_string(buf);
    1555                 :    2535266 : }
    1556                 :            : 
    1557                 :            : // Return the index of a package.
    1558                 :            : 
    1559                 :            : int
    1560                 :      19272 : Export::package_index(const Package* pkg) const
    1561                 :            : {
    1562                 :      19272 :   Unordered_map(const Package *, int)::const_iterator p =
    1563                 :      19272 :     this->packages_.find(pkg);
    1564                 :      19272 :   go_assert(p != this->packages_.end());
    1565                 :      19272 :   int index = p->second;
    1566                 :      19272 :   go_assert(index != 0);
    1567                 :      19272 :   return index;
    1568                 :            : }
    1569                 :            : 
    1570                 :            : // Return the index of the "unsafe" package.
    1571                 :            : 
    1572                 :            : int
    1573                 :          0 : Export::unsafe_package_index() const
    1574                 :            : {
    1575                 :          0 :   for (Unordered_map(const Package*, int)::const_iterator p =
    1576                 :          0 :          this->packages_.begin();
    1577                 :          0 :        p != this->packages_.end();
    1578                 :          0 :        ++p)
    1579                 :            :     {
    1580                 :          0 :       if (p->first->pkgpath() == "unsafe")
    1581                 :            :         {
    1582                 :          0 :           go_assert(p->second != 0);
    1583                 :          0 :           return p->second;
    1584                 :            :         }
    1585                 :            :     }
    1586                 :          0 :   go_unreachable();
    1587                 :            : }
    1588                 :            : 
    1589                 :            : // Return the index of a type.
    1590                 :            : 
    1591                 :            : int
    1592                 :    1554534 : Export::type_index(const Type* type)
    1593                 :            : {
    1594                 :    1554534 :   type = type->forwarded();
    1595                 :    1554534 :   Type_refs::const_iterator p = this->impl_->type_refs.find(type);
    1596                 :    1554534 :   go_assert(p != this->impl_->type_refs.end());
    1597                 :    1554534 :   int index = p->second;
    1598                 :    1554534 :   go_assert(index != 0);
    1599                 :    1554534 :   return index;
    1600                 :            : }
    1601                 :            : 
    1602                 :            : // Export a type.
    1603                 :            : 
    1604                 :            : void
    1605                 :    1522120 : Export::write_type(const Type* type)
    1606                 :            : {
    1607                 :    1522120 :   int index = this->type_index(type);
    1608                 :    1522120 :   char buf[30];
    1609                 :    1522120 :   snprintf(buf, sizeof buf, "<type %d>", index);
    1610                 :    1522120 :   this->write_c_string(buf);
    1611                 :    1522120 : }
    1612                 :            : 
    1613                 :            : // Export a type to a function body.
    1614                 :            : 
    1615                 :            : void
    1616                 :      32414 : Export::write_type_to(const Type* type, Export_function_body* efb)
    1617                 :            : {
    1618                 :      32414 :   int index = this->type_index(type);
    1619                 :      32414 :   char buf[30];
    1620                 :      32414 :   snprintf(buf, sizeof buf, "<type %d>", index);
    1621                 :      32414 :   efb->write_c_string(buf);
    1622                 :      32414 : }
    1623                 :            : 
    1624                 :            : // Export escape note.
    1625                 :            : 
    1626                 :            : void
    1627                 :     783210 : Export::write_escape(std::string* note)
    1628                 :            : {
    1629                 :    1462205 :   if (note != NULL && *note != "esc:0x0")
    1630                 :            :     {
    1631                 :     327760 :       this->write_c_string(" ");
    1632                 :     327760 :       char buf[50];
    1633                 :     327760 :       go_assert(note->find("esc:") != std::string::npos);
    1634                 :     327760 :       snprintf(buf, sizeof buf, "<%s>", note->c_str());
    1635                 :     327760 :       this->write_c_string(buf);
    1636                 :            :     }
    1637                 :     783210 : }
    1638                 :            : 
    1639                 :            : // Add the builtin types to the export table.
    1640                 :            : 
    1641                 :            : void
    1642                 :       4251 : Export::register_builtin_types(Gogo* gogo)
    1643                 :            : {
    1644                 :       4251 :   this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
    1645                 :       4251 :   this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
    1646                 :       4251 :   this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
    1647                 :       4251 :   this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
    1648                 :       4251 :   this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
    1649                 :       4251 :   this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
    1650                 :       4251 :   this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
    1651                 :       4251 :   this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
    1652                 :       4251 :   this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
    1653                 :       4251 :   this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
    1654                 :       4251 :   this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
    1655                 :       4251 :   this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
    1656                 :       4251 :   this->register_builtin_type(gogo, "int", BUILTIN_INT);
    1657                 :       4251 :   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
    1658                 :       4251 :   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
    1659                 :       4251 :   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
    1660                 :       4251 :   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
    1661                 :       4251 :   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
    1662                 :       4251 :   this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
    1663                 :       4251 :   this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
    1664                 :       4251 : }
    1665                 :            : 
    1666                 :            : // Register one builtin type in the export table.
    1667                 :            : 
    1668                 :            : void
    1669                 :      85020 : Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
    1670                 :            : {
    1671                 :      85020 :   Named_object* named_object = gogo->lookup_global(name);
    1672                 :      85020 :   go_assert(named_object != NULL && named_object->is_type());
    1673                 :      85020 :   std::pair<Type_refs::iterator, bool> ins =
    1674                 :      85020 :     this->impl_->type_refs.insert(std::make_pair(named_object->type_value(), code));
    1675                 :      85020 :   go_assert(ins.second);
    1676                 :            : 
    1677                 :            :   // We also insert the underlying type.  We can see the underlying
    1678                 :            :   // type at least for string and bool.  It's OK if this insert
    1679                 :            :   // fails--we expect duplications here, and it doesn't matter when
    1680                 :            :   // they occur.
    1681                 :      85020 :   Type* real_type = named_object->type_value()->real_type();
    1682                 :      85020 :   this->impl_->type_refs.insert(std::make_pair(real_type, code));
    1683                 :      85020 : }
    1684                 :            : 
    1685                 :            : // Class Export::Stream.
    1686                 :            : 
    1687                 :       8502 : Export::Stream::Stream()
    1688                 :            : {
    1689                 :       8502 :   this->sha1_helper_ = go_create_sha1_helper();
    1690                 :       8502 :   go_assert(this->sha1_helper_ != NULL);
    1691                 :       8502 : }
    1692                 :            : 
    1693                 :       8502 : Export::Stream::~Stream()
    1694                 :            : {
    1695                 :       8502 : }
    1696                 :            : 
    1697                 :            : // Write bytes to the stream.  This keeps a checksum of bytes as they
    1698                 :            : // go by.
    1699                 :            : 
    1700                 :            : void
    1701                 :   16280066 : Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
    1702                 :            : {
    1703                 :   16280066 :   this->sha1_helper_->process_bytes(bytes, length);
    1704                 :   16280066 :   this->do_write(bytes, length);
    1705                 :   16280066 : }
    1706                 :            : 
    1707                 :            : // Get the checksum.
    1708                 :            : 
    1709                 :            : std::string
    1710                 :       4251 : Export::Stream::checksum()
    1711                 :            : {
    1712                 :       4251 :   std::string rval = this->sha1_helper_->finish();
    1713                 :       4251 :   delete this->sha1_helper_;
    1714                 :       4251 :   return rval;
    1715                 :            : }
    1716                 :            : 
    1717                 :            : // Write the checksum string to the export data.
    1718                 :            : 
    1719                 :            : void
    1720                 :       4251 : Export::Stream::write_checksum(const std::string& s)
    1721                 :            : {
    1722                 :       4251 :   this->do_write(s.data(), s.length());
    1723                 :       4251 : }
    1724                 :            : 
    1725                 :            : // Class Stream_to_section.
    1726                 :            : 
    1727                 :       4251 : Stream_to_section::Stream_to_section(Backend* backend)
    1728                 :       4251 :     : backend_(backend)
    1729                 :            : {
    1730                 :       4251 : }
    1731                 :            : 
    1732                 :            : // Write data to a section.
    1733                 :            : 
    1734                 :            : void
    1735                 :    7150833 : Stream_to_section::do_write(const char* bytes, size_t length)
    1736                 :            : {
    1737                 :    7150833 :   this->backend_->write_export_data (bytes, length);
    1738                 :    7150833 : }
    1739                 :            : 
    1740                 :            : // Class Export_function_body.
    1741                 :            : 
    1742                 :            : // Record a temporary statement.
    1743                 :            : 
    1744                 :            : unsigned int
    1745                 :       4502 : Export_function_body::record_temporary(const Temporary_statement* temp)
    1746                 :            : {
    1747                 :       4502 :   unsigned int ret = this->next_temporary_index_;
    1748                 :       4502 :   if (ret > 0x7fffffff)
    1749                 :          0 :     go_error_at(temp->location(),
    1750                 :            :                 "too many temporary statements in export data");
    1751                 :       4502 :   ++this->next_temporary_index_;
    1752                 :       4502 :   std::pair<const Temporary_statement*, unsigned int> val(temp, ret);
    1753                 :       4502 :   std::pair<Unordered_map(const Temporary_statement*, unsigned int)::iterator,
    1754                 :       4502 :             bool> ins = this->temporary_indexes_.insert(val);
    1755                 :       4502 :   go_assert(ins.second);
    1756                 :       4502 :   return ret;
    1757                 :            : }
    1758                 :            : 
    1759                 :            : // Return the index of a temporary statement.
    1760                 :            : 
    1761                 :            : unsigned int
    1762                 :       6732 : Export_function_body::temporary_index(const Temporary_statement* temp)
    1763                 :            : {
    1764                 :       6732 :   Unordered_map(const Temporary_statement*, unsigned int)::const_iterator p =
    1765                 :       6732 :     this->temporary_indexes_.find(temp);
    1766                 :       6732 :   go_assert(p != this->temporary_indexes_.end());
    1767                 :       6732 :   return p->second;
    1768                 :            : }
    1769                 :            : 
    1770                 :            : // Return the index of an unnamed label.  If it doesn't already have
    1771                 :            : // an index, give it one.
    1772                 :            : 
    1773                 :            : unsigned int
    1774                 :       3344 : Export_function_body::unnamed_label_index(const Unnamed_label* label)
    1775                 :            : {
    1776                 :       3344 :   unsigned int next = this->next_label_index_;
    1777                 :       3344 :   std::pair<const Unnamed_label*, unsigned int> val(label, next);
    1778                 :       3344 :   std::pair<Unordered_map(const Unnamed_label*, unsigned int)::iterator,
    1779                 :            :             bool> ins =
    1780                 :       3344 :     this->label_indexes_.insert(val);
    1781                 :       3344 :   if (!ins.second)
    1782                 :       1703 :     return ins.first->second;
    1783                 :            :   else
    1784                 :            :     {
    1785                 :       1641 :       if (next > 0x7fffffff)
    1786                 :          0 :         go_error_at(label->location(),
    1787                 :            :                     "too many unnamed labels in export data");
    1788                 :       1641 :       ++this->next_label_index_;
    1789                 :       1641 :       return next;
    1790                 :            :     }
    1791                 :            : }

Generated by: LCOV version 1.16+git.20220603.dfeb750

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.