LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - export.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.7 % 840 737
Test Date: 2024-03-23 14:05:01 Functions: 93.9 % 49 46
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                 :     2673250 :   operator()(const Type* type) const
      51                 :             :   {
      52                 :     2673250 :     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                 :     5626761 :   operator()(const Type* t1, const Type* t2) const
      65                 :             :   {
      66                 :     5625813 :     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                 :        4252 : struct Export_impl {
      83                 :             :   Type_refs type_refs;
      84                 :             : };
      85                 :             : 
      86                 :             : // Constructor.
      87                 :             : 
      88                 :        4252 : Export::Export(Stream* stream)
      89                 :        4252 :     : stream_(stream), type_index_(1), packages_(), impl_(new Export_impl)
      90                 :             : {
      91                 :        4252 :   go_assert(Export::checksum_len == Go_sha1_helper::checksum_len);
      92                 :        4252 : }
      93                 :             : 
      94                 :             : // Destructor.
      95                 :             : 
      96                 :        4252 : Export::~Export()
      97                 :             : {
      98                 :        8504 :   delete this->impl_;
      99                 :        4252 : }
     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                 :        4252 :   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                 :        4252 :     : Traverse(traverse_expressions
     113                 :             :                | traverse_types),
     114                 :        4252 :       exp_(exp), packages_(packages), exports_(exports), imports_(imports),
     115                 :        4252 :       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                 :        4252 : Collect_export_references::expand_exports(std::vector<Named_object*>* fcns)
     176                 :             : {
     177                 :        4252 :   this->inline_fcn_worklist_ = fcns;
     178                 :       49670 :   while (!this->inline_fcn_worklist_->empty())
     179                 :             :     {
     180                 :       45418 :       Named_object* no = this->inline_fcn_worklist_->back();
     181                 :       45418 :       this->inline_fcn_worklist_->pop_back();
     182                 :       45418 :       std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
     183                 :       45418 :         this->checked_functions_.insert(no);
     184                 :       45418 :       if (ins.second)
     185                 :             :         {
     186                 :             :           // This traversal may add new objects to this->exports_ and new
     187                 :             :           // functions to this->inline_fcn_worklist_.
     188                 :       41219 :           no->func_value()->block()->traverse(this);
     189                 :             :         }
     190                 :             :     }
     191                 :        4252 :   this->inline_fcn_worklist_ = NULL;
     192                 :        4252 :   this->exports_finalized_ = true;
     193                 :        4252 : }
     194                 :             : 
     195                 :             : bool
     196                 :       53699 : Collect_export_references::add_to_exports(Named_object* no)
     197                 :             : {
     198                 :       53699 :   std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
     199                 :       53699 :       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                 :       53699 :   go_assert(!this->exports_finalized_ || !ins.second);
     203                 :       53699 :   return ins.second;
     204                 :             : }
     205                 :             : 
     206                 :             : int
     207                 :      614729 : Collect_export_references::expression(Expression** pexpr)
     208                 :             : {
     209                 :      614729 :   const Expression* expr = *pexpr;
     210                 :             : 
     211                 :      614729 :   const Var_expression* ve = expr->var_expression();
     212                 :      614729 :   if (ve != NULL)
     213                 :             :     {
     214                 :      208115 :       Named_object* no = ve->named_object();
     215                 :      208115 :       if (no->is_variable() && no->var_value()->is_global())
     216                 :             :         {
     217                 :       20934 :           const Package* var_package = no->package();
     218                 :       20934 :           if (var_package != NULL)
     219                 :        3489 :             this->imports_->insert(var_package);
     220                 :             : 
     221                 :       20934 :           this->add_to_exports(no);
     222                 :       20934 :           no->var_value()->set_is_referenced_by_inline();
     223                 :             :         }
     224                 :      208115 :       return TRAVERSE_CONTINUE;
     225                 :             :     }
     226                 :             : 
     227                 :      406614 :   const Func_expression* fe = expr->func_expression();
     228                 :      406614 :   if (fe != NULL)
     229                 :             :     {
     230                 :       59239 :       Named_object* no = fe->named_object();
     231                 :             : 
     232                 :       59239 :       const Package* func_package = fe->named_object()->package();
     233                 :       59239 :       if (func_package != NULL)
     234                 :       19055 :         this->imports_->insert(func_package);
     235                 :             : 
     236                 :       59239 :       if (no->is_function_declaration()
     237                 :       59239 :           && no->func_declaration_value()->type()->is_builtin())
     238                 :             :         return TRAVERSE_CONTINUE;
     239                 :             : 
     240                 :       42859 :       if (this->inline_fcn_worklist_ != NULL)
     241                 :             :         {
     242                 :       32765 :           bool added = this->add_to_exports(no);
     243                 :             : 
     244                 :       32765 :           if (no->is_function())
     245                 :       17564 :             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                 :       32765 :           if (added
     252                 :       18213 :               && no->is_function()
     253                 :       39853 :               && no->func_value()->export_for_inlining())
     254                 :        4199 :             this->inline_fcn_worklist_->push_back(no);
     255                 :             :         }
     256                 :             : 
     257                 :       42859 :       return TRAVERSE_CONTINUE;
     258                 :             :     }
     259                 :             : 
     260                 :      347375 :   const Named_object* nco = expr->named_constant();
     261                 :      347375 :   if (nco != 0)
     262                 :             :     {
     263                 :       37774 :       const Named_constant *nc = nco->const_value();
     264                 :       37774 :       Type::traverse(nc->type(), this);
     265                 :       37774 :       return TRAVERSE_CONTINUE;
     266                 :             :     }
     267                 :             : 
     268                 :      309601 :   const Call_expression* call = expr->call_expression();
     269                 :       58805 :   if (call != NULL)
     270                 :             :     {
     271                 :       58805 :       const Builtin_call_expression* bce = call->builtin_call_expression();
     272                 :       16380 :       if (bce != NULL
     273                 :       16380 :           && (bce->code() == Builtin_call_expression::BUILTIN_ADD
     274                 :       16380 :               || 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                 :        4252 : Collect_export_references::prepare_expressions(const std::vector<Named_object*>& sorted_exports)
     296                 :             : {
     297                 :      111514 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     298                 :      111514 :        p != sorted_exports.end();
     299                 :      107262 :        ++p)
     300                 :             :     {
     301                 :      107262 :       Named_object* no = *p;
     302                 :      107262 :       if (no->classification() == Named_object::NAMED_OBJECT_CONST)
     303                 :             :         {
     304                 :       39147 :           Expression* e = no->const_value()->expr();
     305                 :       39147 :           if (e != NULL)
     306                 :       39147 :             Expression::traverse(&e, this);
     307                 :             :         }
     308                 :             :     }
     309                 :        4252 : }
     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                 :        4252 : 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                 :      111514 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     321                 :      111514 :        p != sorted_exports.end();
     322                 :      107262 :        ++p)
     323                 :             :     {
     324                 :      107262 :       Named_object* no = *p;
     325                 :      107262 :       switch (no->classification())
     326                 :             :         {
     327                 :       39147 :         case Named_object::NAMED_OBJECT_CONST:
     328                 :       39147 :           {
     329                 :       39147 :             Type* t = no->const_value()->type();
     330                 :       39147 :             if (t != NULL && !t->is_abstract())
     331                 :       15584 :               Type::traverse(t, this);
     332                 :             :           }
     333                 :             :           break;
     334                 :             : 
     335                 :       11409 :         case Named_object::NAMED_OBJECT_TYPE:
     336                 :       11409 :           Type::traverse(no->type_value()->real_type(), this);
     337                 :       11409 :           this->traverse_named_type(no->type_value());
     338                 :       11409 :           break;
     339                 :             : 
     340                 :        8438 :         case Named_object::NAMED_OBJECT_VAR:
     341                 :        8438 :           Type::traverse(no->var_value()->type(), this);
     342                 :        8438 :           break;
     343                 :             : 
     344                 :       36548 :         case Named_object::NAMED_OBJECT_FUNC:
     345                 :       36548 :           {
     346                 :       36548 :             Function* fn = no->func_value();
     347                 :       36548 :             this->traverse_function_type(fn->type());
     348                 :       36548 :             if (fn->export_for_inlining())
     349                 :        9453 :               fn->block()->traverse(this);
     350                 :             :           }
     351                 :             :           break;
     352                 :             : 
     353                 :       11720 :         case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
     354                 :       11720 :           this->traverse_function_type(no->func_declaration_value()->type());
     355                 :       11720 :           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                 :        4252 : }
     364                 :             : 
     365                 :             : // Record referenced type, record package imports, and make sure we traverse
     366                 :             : // methods of named types.
     367                 :             : 
     368                 :             : int
     369                 :     1017597 : Collect_export_references::type(Type* type)
     370                 :             : {
     371                 :             :   // Skip forwarders; don't try to give them a type index.
     372                 :     1236087 :   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                 :      768659 :   if (type->is_void_type())
     379                 :             :     return TRAVERSE_SKIP_COMPONENTS;
     380                 :             : 
     381                 :             :   // Skip the nil type, turns up in function bodies.
     382                 :      767978 :   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                 :      760646 :   if (type->is_abstract())
     388                 :             :     return TRAVERSE_SKIP_COMPONENTS;
     389                 :             : 
     390                 :      700677 :   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                 :      230048 :   if (type->classification() == Type::TYPE_INTERFACE)
     403                 :             :     {
     404                 :       11558 :       Interface_type* it = type->interface_type();
     405                 :       11558 :       const Typed_identifier_list* methods = it->local_methods();
     406                 :       11558 :       if (methods != NULL)
     407                 :             :         {
     408                 :       51537 :           for (Typed_identifier_list::const_iterator p = methods->begin();
     409                 :       51537 :                p != methods->end();
     410                 :       39979 :                ++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                 :       11558 :       return TRAVERSE_SKIP_COMPONENTS;
     419                 :             :     }
     420                 :             : 
     421                 :      218490 :   Named_type* nt = type->named_type();
     422                 :      218490 :   if (nt != NULL)
     423                 :       73269 :     this->traverse_named_type(nt);
     424                 :             : 
     425                 :             :   return TRAVERSE_CONTINUE;
     426                 :             : }
     427                 :             : 
     428                 :             : void
     429                 :       84678 : Collect_export_references::traverse_named_type(Named_type* nt)
     430                 :             : {
     431                 :       84678 :   const Package* package = nt->named_object()->package();
     432                 :       84678 :   if (package != NULL)
     433                 :       59569 :     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                 :       84678 :   const Bindings* methods = nt->local_methods();
     439                 :       84678 :   if (methods != NULL)
     440                 :             :     {
     441                 :      116892 :       for (Bindings::const_definitions_iterator pm =
     442                 :       46965 :              methods->begin_definitions();
     443                 :      116892 :            pm != methods->end_definitions();
     444                 :       69927 :            ++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                 :      361013 :            ++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                 :       84678 : }
     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                 :      446544 : Collect_export_references::traverse_function_type(Function_type* type)
     469                 :             : {
     470                 :      446544 :   go_assert(type != NULL);
     471                 :      446544 :   if (this->remember_type(type))
     472                 :             :     return;
     473                 :      446544 :   const Typed_identifier* receiver = type->receiver();
     474                 :      446544 :   if (receiver != NULL)
     475                 :      361013 :     Type::traverse(receiver->type(), this);
     476                 :      446544 :   const Typed_identifier_list* parameters = type->parameters();
     477                 :      446544 :   if (parameters != NULL)
     478                 :      226217 :     parameters->traverse(this);
     479                 :      446544 :   const Typed_identifier_list* results = type->results();
     480                 :      446544 :   if (results != NULL)
     481                 :      340940 :     results->traverse(this);
     482                 :             : }
     483                 :             : 
     484                 :             : // Return true if we should export NO.
     485                 :             : 
     486                 :             : static bool
     487                 :      448171 : should_export(Named_object* no)
     488                 :             : {
     489                 :             :   // We only export objects which are locally defined.
     490                 :      448171 :   if (no->package() != NULL)
     491                 :             :     return false;
     492                 :             : 
     493                 :             :   // We don't export packages.
     494                 :      415500 :   if (no->is_package())
     495                 :             :     return false;
     496                 :             : 
     497                 :             :   // We don't export hidden names.
     498                 :      376170 :   if (Gogo::is_hidden_name(no->name()))
     499                 :             :     return false;
     500                 :             : 
     501                 :             :   // We don't export various special functions.
     502                 :      164449 :   if (Gogo::special_name_pos(no->name()) != std::string::npos)
     503                 :             :     return false;
     504                 :             : 
     505                 :             :   // Methods are exported with the type, not here.
     506                 :      116327 :   if (no->is_function()
     507                 :      116327 :       && no->func_value()->type()->is_method())
     508                 :             :     return false;
     509                 :       85650 :   if (no->is_function_declaration()
     510                 :       85650 :       && 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                 :       85650 :   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                 :     1457591 :   operator()(const Named_object* n1, const Named_object* n2) const
     532                 :             :   {
     533                 :     1457591 :     if (n1 == n2)
     534                 :             :       return false;
     535                 :             : 
     536                 :     1457591 :     if (n1->package() != n2->package())
     537                 :             :       {
     538                 :      324231 :         if (n1->package() == NULL)
     539                 :             :           return true;
     540                 :      282348 :         if (n2->package() == NULL)
     541                 :             :           return false;
     542                 :             : 
     543                 :             :         // Make sure we don't see the same pkgpath twice.
     544                 :      256852 :         const std::string& p1(n1->package()->pkgpath());
     545                 :      256852 :         const std::string& p2(n2->package()->pkgpath());
     546                 :      256852 :         go_assert(p1 != p2);
     547                 :             : 
     548                 :      256852 :         return p1 < p2;
     549                 :             :       }
     550                 :             : 
     551                 :     1133360 :     if (n1->name() != n2->name())
     552                 :     1133355 :       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                 :     1974771 :   operator()(const Type* t1, const Type* t2) const
     602                 :             :   {
     603                 :     1974771 :     t1 = t1->forwarded();
     604                 :     1974771 :     t2 = t2->forwarded();
     605                 :             : 
     606                 :     1974771 :     const Named_type* nt1 = t1->named_type();
     607                 :     1974771 :     const Named_type* nt2 = t2->named_type();
     608                 :     1974771 :     if (nt1 != NULL)
     609                 :             :       {
     610                 :      604941 :         if (nt2 != NULL)
     611                 :             :           {
     612                 :      462209 :             Sort_bindings sb;
     613                 :      462209 :             return sb(nt1->named_object(), nt2->named_object());
     614                 :             :           }
     615                 :             :         else
     616                 :             :           return true;
     617                 :             :       }
     618                 :     1369830 :     else if (nt2 != NULL)
     619                 :             :       return false;
     620                 :     1293927 :     if (t1->classification() != t2->classification())
     621                 :      450316 :       return t1->classification() < t2->classification();
     622                 :      843611 :     Gogo* gogo = go_get_gogo();
     623                 :      843611 :     Backend_name b1;
     624                 :      843611 :     gogo->type_descriptor_backend_name(t1, NULL, &b1);
     625                 :      843611 :     Backend_name b2;
     626                 :      843611 :     gogo->type_descriptor_backend_name(t2, NULL, &b2);
     627                 :             : 
     628                 :      843611 :     std::string n1 = b1.name();
     629                 :      843611 :     std::string n2 = b2.name();
     630                 :      843611 :     if (n1 != n2)
     631                 :      843143 :       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                 :         468 :     if (t1 == t2)
     641                 :             :       return false;
     642                 :             : 
     643                 :         468 :     Sort_types sort;
     644                 :         468 :     Type_alias_identical identical;
     645                 :         468 :     go_assert(!identical(t1, t2));
     646                 :             : 
     647                 :         468 :     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                 :          18 :       case Type::TYPE_FUNCTION:
     667                 :          18 :         {
     668                 :          18 :           const Function_type* ft1 = t1->function_type();
     669                 :          18 :           const Function_type* ft2 = t2->function_type();
     670                 :          18 :           const Typed_identifier* r1 = ft1->receiver();
     671                 :          18 :           const Typed_identifier* r2 = ft2->receiver();
     672                 :          18 :           if (r1 == NULL)
     673                 :          18 :             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                 :          18 :           const Typed_identifier_list* p1 = ft1->parameters();
     684                 :          18 :           const Typed_identifier_list* p2 = ft2->parameters();
     685                 :          18 :           if (p1 == NULL || p1->empty())
     686                 :           3 :             go_assert(p2 == NULL || p2->empty());
     687                 :             :           else
     688                 :             :             {
     689                 :          15 :               go_assert(p2 != NULL && !p2->empty());
     690                 :          15 :               int i = compare_til(p1, p2);
     691                 :          15 :               if (i < 0)
     692                 :             :                 return false;
     693                 :           5 :               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                 :         175 :       case Type::TYPE_POINTER:
     715                 :         175 :         {
     716                 :         175 :           const Type* p1 = t1->points_to()->forwarded();
     717                 :         175 :           const Type* p2 = t2->points_to()->forwarded();
     718                 :         175 :           go_assert(!identical(p1, p2));
     719                 :         175 :           return sort(p1, p2);
     720                 :             :         }
     721                 :             : 
     722                 :           0 :       case Type::TYPE_STRUCT:
     723                 :           0 :         {
     724                 :           0 :           const Struct_type* s1 = t1->struct_type();
     725                 :           0 :           const Struct_type* s2 = t2->struct_type();
     726                 :           0 :           const Struct_field_list* f1 = s1->fields();
     727                 :           0 :           const Struct_field_list* f2 = s2->fields();
     728                 :           0 :           go_assert(f1 != NULL && f2 != NULL);
     729                 :           0 :           Struct_field_list::const_iterator p1 = f1->begin();
     730                 :           0 :           Struct_field_list::const_iterator p2 = f2->begin();
     731                 :           0 :           for (; p2 != f2->end(); ++p1, ++p2)
     732                 :             :             {
     733                 :           0 :               go_assert(p1 != f1->end());
     734                 :           0 :               go_assert(p1->field_name() == p2->field_name());
     735                 :           0 :               go_assert(p1->is_anonymous() == p2->is_anonymous());
     736                 :           0 :               const Type* ft1 = p1->type()->forwarded();
     737                 :           0 :               const Type* ft2 = p2->type()->forwarded();
     738                 :           0 :               if (!identical(ft1, ft2))
     739                 :           0 :                 return sort(ft1, ft2);
     740                 :             :             }
     741                 :           0 :           go_assert(p1 == f1->end());
     742                 :           0 :           go_unreachable();
     743                 :             :         }
     744                 :             : 
     745                 :         244 :       case Type::TYPE_ARRAY:
     746                 :         244 :         {
     747                 :         488 :           const Type* e1 = t1->array_type()->element_type()->forwarded();
     748                 :         488 :           const Type* e2 = t2->array_type()->element_type()->forwarded();
     749                 :         244 :           go_assert(!identical(e1, e2));
     750                 :         244 :           return sort(e1, e2);
     751                 :             :         }
     752                 :             : 
     753                 :           6 :       case Type::TYPE_MAP:
     754                 :           6 :         {
     755                 :           6 :           const Map_type* m1 = t1->map_type();
     756                 :           6 :           const Map_type* m2 = t2->map_type();
     757                 :           6 :           const Type* k1 = m1->key_type()->forwarded();
     758                 :           6 :           const Type* k2 = m2->key_type()->forwarded();
     759                 :           6 :           if (!identical(k1, k2))
     760                 :           0 :             return sort(k1, k2);
     761                 :           6 :           const Type* v1 = m1->val_type()->forwarded();
     762                 :           6 :           const Type* v2 = m2->val_type()->forwarded();
     763                 :           6 :           go_assert(!identical(v1, v2));
     764                 :           6 :           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                 :           0 :               go_assert(m2 != NULL && !m2->empty());
     789                 :             :               return true;
     790                 :             :             }
     791                 :          25 :           else if (m2 == NULL || m2->empty())
     792                 :             :             {
     793                 :             :               go_assert(m1 != NULL && !m1->empty());
     794                 :             :               return false;
     795                 :             :             }
     796                 :             : 
     797                 :          25 :           int i = compare_til(m1, m2);
     798                 :          25 :           if (i < 0)
     799                 :             :             return false;
     800                 :           2 :           else if (i > 0)
     801                 :             :             return true;
     802                 :             :           else
     803                 :           0 :             go_unreachable();
     804                 :             :         }
     805                 :             :       }
     806                 :      843611 :   }
     807                 :             : };
     808                 :             : 
     809                 :             : // Compare Typed_identifier_list's with Sort_types, returning -1, 0, +1.
     810                 :             : 
     811                 :             : static int
     812                 :          43 : compare_til(
     813                 :             :     const Typed_identifier_list* til1,
     814                 :             :     const Typed_identifier_list* til2)
     815                 :             : {
     816                 :          43 :   Type_alias_identical identical;
     817                 :          43 :   Sort_types sort;
     818                 :          43 :   Typed_identifier_list::const_iterator p1 = til1->begin();
     819                 :          43 :   Typed_identifier_list::const_iterator p2 = til2->begin();
     820                 :          49 :   for (; p2 != til2->end(); ++p1, ++p2)
     821                 :             :     {
     822                 :          49 :       if (p1 == til1->end())
     823                 :             :         return -1;
     824                 :          49 :       const Type* t1 = p1->type()->forwarded();
     825                 :          49 :       const Type* t2 = p2->type()->forwarded();
     826                 :          49 :       if (!identical(t1, t2))
     827                 :             :         {
     828                 :          43 :           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                 :        4252 : 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                 :        4252 :   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                 :        4252 :   Unordered_set(Named_object*) exports;
     863                 :        4252 :   std::vector<Named_object*> check_inline_refs;
     864                 :        4252 :   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                 :       45471 :   for (Unordered_set(Named_object*)::const_iterator p = functions_marked_inline->begin();
     869                 :       45471 :        p != functions_marked_inline->end();
     870                 :       41219 :        ++p)
     871                 :       41219 :       check_inline_refs.push_back(*p);
     872                 :             : 
     873                 :      448635 :   for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
     874                 :      448635 :        p != bindings->end_definitions();
     875                 :      444383 :        ++p)
     876                 :             :     {
     877                 :      444383 :       if (should_export(*p))
     878                 :       84342 :         exports.insert(*p);
     879                 :             :     }
     880                 :             : 
     881                 :      333240 :   for (Bindings::const_declarations_iterator p =
     882                 :        4252 :          bindings->begin_declarations();
     883                 :      333240 :        p != bindings->end_declarations();
     884                 :      328988 :        ++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                 :      328988 :       if (p->second->is_function_declaration()
     889                 :      332776 :           && should_export(p->second))
     890                 :         595 :         exports.insert(p->second);
     891                 :             :     }
     892                 :             : 
     893                 :             :   // Track all imported packages mentioned in export data.
     894                 :        4252 :   Unordered_set(const Package*) all_imports;
     895                 :             : 
     896                 :        4252 :   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                 :        4252 :   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                 :        4252 :   std::vector<Named_object*> sorted_exports;
     906                 :        4252 :   sorted_exports.reserve(exports.size());
     907                 :             : 
     908                 :      111514 :   for (Unordered_set(Named_object*)::const_iterator p = exports.begin();
     909                 :      111514 :        p != exports.end();
     910                 :      107262 :        ++p)
     911                 :             :     {
     912                 :      107262 :       sorted_exports.push_back(*p);
     913                 :             : 
     914                 :      107262 :       const Package* pkg = (*p)->package();
     915                 :      107262 :       if (pkg != NULL)
     916                 :       14577 :         all_imports.insert(pkg);
     917                 :             :     }
     918                 :             : 
     919                 :        4252 :   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                 :        4252 :   collect.prepare_types(sorted_exports);
     924                 :        4252 :   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                 :        4252 :   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                 :        4252 :   this->write_bytes(Export::cur_magic, Export::magic_len);
     935                 :             : 
     936                 :             :   // The package name.
     937                 :        4252 :   this->write_c_string("package ");
     938                 :        4252 :   this->write_string(package_name);
     939                 :        4252 :   this->write_c_string("\n");
     940                 :             : 
     941                 :             :   // The prefix or package path, used for all global symbols.
     942                 :        4252 :   if (prefix.empty())
     943                 :             :     {
     944                 :        3642 :       go_assert(!pkgpath.empty());
     945                 :        3642 :       this->write_c_string("pkgpath ");
     946                 :        3642 :       this->write_string(pkgpath);
     947                 :             :     }
     948                 :             :   else
     949                 :             :     {
     950                 :         610 :       this->write_c_string("prefix ");
     951                 :         610 :       this->write_string(prefix);
     952                 :             :     }
     953                 :        4252 :   this->write_c_string("\n");
     954                 :             : 
     955                 :        4252 :   this->write_packages(packages);
     956                 :             : 
     957                 :        4252 :   this->write_imports(imports, all_imports);
     958                 :             : 
     959                 :        4252 :   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                 :        4252 :   this->write_types(unexported_type_index);
     968                 :             : 
     969                 :             :   // Write out the non-type export data.
     970                 :      111514 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     971                 :      111514 :        p != sorted_exports.end();
     972                 :      107262 :        ++p)
     973                 :             :     {
     974                 :      107262 :       if (!(*p)->is_type())
     975                 :       95853 :         (*p)->export_named_object(this);
     976                 :             :     }
     977                 :             : 
     978                 :        4252 :   std::string checksum = this->stream_->checksum();
     979                 :        4252 :   std::string s = "checksum ";
     980                 :        4252 :   for (std::string::const_iterator p = checksum.begin();
     981                 :       89292 :        p != checksum.end();
     982                 :       85040 :        ++p)
     983                 :             :     {
     984                 :       85040 :       unsigned char c = *p;
     985                 :       85040 :       unsigned int dig = c >> 4;
     986                 :       85040 :       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
     987                 :       85040 :       dig = c & 0xf;
     988                 :      170080 :       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
     989                 :             :     }
     990                 :        4252 :   s += "\n";
     991                 :        4252 :   this->stream_->write_checksum(s);
     992                 :       12756 : }
     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                 :      712086 : Export::record_type(Type* type)
     999                 :             : {
    1000                 :      712086 :   type = type->forwarded();
    1001                 :      712086 :   std::pair<Type_refs::iterator, bool> ins =
    1002                 :      712086 :     this->impl_->type_refs.insert(std::make_pair(type, 0));
    1003                 :      712086 :   return ins.second;
    1004                 :             : }
    1005                 :             : 
    1006                 :             : // Assign the specified type an index.
    1007                 :             : 
    1008                 :             : void
    1009                 :      233149 : Export::set_type_index(const Type* type)
    1010                 :             : {
    1011                 :      233149 :   type = type->forwarded();
    1012                 :      233149 :   Type_refs::iterator p = this->impl_->type_refs.find(type);
    1013                 :      233149 :   go_assert(p != this->impl_->type_refs.end());
    1014                 :      233149 :   int index = this->type_index_;
    1015                 :      233149 :   ++this->type_index_;
    1016                 :      233149 :   go_assert(p->second == 0);
    1017                 :      233149 :   p->second = index;
    1018                 :      233149 : }
    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                 :        4252 : Export::assign_type_indices(const std::vector<Named_object*>& sorted_exports)
    1028                 :             : {
    1029                 :             :   // Assign indexes to all the exported types.
    1030                 :      111514 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
    1031                 :      111514 :        p != sorted_exports.end();
    1032                 :      107262 :        ++p)
    1033                 :             :     {
    1034                 :      107262 :       if (!(*p)->is_type())
    1035                 :       95853 :         continue;
    1036                 :       11409 :       this->record_type((*p)->type_value());
    1037                 :       11409 :       this->set_type_index((*p)->type_value());
    1038                 :             :     }
    1039                 :        4252 :   int ret = this->type_index_;
    1040                 :             : 
    1041                 :             :   // Collect export-referenced, non-builtin types.
    1042                 :        4252 :   std::vector<const Type*> types;
    1043                 :        4252 :   types.reserve(this->impl_->type_refs.size());
    1044                 :      394725 :   for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
    1045                 :      394725 :        p != this->impl_->type_refs.end();
    1046                 :      390473 :        ++p)
    1047                 :             :     {
    1048                 :      390473 :       const Type* t = p->first;
    1049                 :      390473 :       if (p->second != 0)
    1050                 :      168733 :         continue;
    1051                 :      221740 :       types.push_back(t);
    1052                 :             :     }
    1053                 :             : 
    1054                 :             :   // Sort the types.
    1055                 :        4252 :   std::sort(types.begin(), types.end(), Sort_types());
    1056                 :             : 
    1057                 :             :   // Assign numbers to the sorted list.
    1058                 :      225992 :   for (std::vector<const Type *>::const_iterator p = types.begin();
    1059                 :      225992 :        p != types.end();
    1060                 :      221740 :        ++p)
    1061                 :      221740 :     this->set_type_index((*p));
    1062                 :             : 
    1063                 :        8504 :   return ret;
    1064                 :        4252 : }
    1065                 :             : 
    1066                 :             : // Sort packages.
    1067                 :             : 
    1068                 :             : static bool
    1069                 :       13794 : packages_compare(const Package* a, const Package* b)
    1070                 :             : {
    1071                 :       13794 :   if (a->package_name() < b->package_name())
    1072                 :             :     return true;
    1073                 :        7551 :   else if (a->package_name() > b->package_name())
    1074                 :             :     return false;
    1075                 :             : 
    1076                 :           6 :   if (a->pkgpath() < b->pkgpath())
    1077                 :             :     return true;
    1078                 :           0 :   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                 :        4252 : Export::write_packages(const std::map<std::string, Package*>& packages)
    1097                 :             : {
    1098                 :             :   // Sort for consistent output.
    1099                 :        4252 :   std::vector<Package*> out;
    1100                 :      116815 :   for (std::map<std::string, Package*>::const_iterator p = packages.begin();
    1101                 :      116815 :        p != packages.end();
    1102                 :      112563 :        ++p)
    1103                 :             :     {
    1104                 :      112563 :       if (p->second->pkgpath_symbol()
    1105                 :      225126 :           != Gogo::pkgpath_for_symbol(p->second->pkgpath()))
    1106                 :         792 :         out.push_back(p->second);
    1107                 :             :     }
    1108                 :             : 
    1109                 :        4252 :   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                 :         792 :        ++p)
    1114                 :             :     {
    1115                 :         792 :       this->write_c_string("package ");
    1116                 :         792 :       this->write_string((*p)->package_name());
    1117                 :         792 :       this->write_c_string(" ");
    1118                 :         792 :       this->write_string((*p)->pkgpath());
    1119                 :         792 :       this->write_c_string(" ");
    1120                 :         792 :       this->write_string((*p)->pkgpath_symbol());
    1121                 :         792 :       this->write_c_string("\n");
    1122                 :             :     }
    1123                 :        4252 : }
    1124                 :             : 
    1125                 :             : // Sort imported packages.
    1126                 :             : 
    1127                 :             : static bool
    1128                 :       48631 : import_compare(const std::pair<std::string, Package*>& a,
    1129                 :             :                const std::pair<std::string, Package*>& b)
    1130                 :             : {
    1131                 :       48631 :   return a.first < b.first;
    1132                 :             : }
    1133                 :             : 
    1134                 :             : // Write out the imported packages.
    1135                 :             : 
    1136                 :             : void
    1137                 :        4252 : 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                 :        4252 :   Unordered_set(const Package*) seen;
    1142                 :        4252 :   std::vector<std::pair<std::string, Package*> > sorted_imports;
    1143                 :        4252 :   for (std::map<std::string, Package*>::const_iterator p = imports.begin();
    1144                 :       26077 :        p != imports.end();
    1145                 :       21825 :        ++p)
    1146                 :             :     {
    1147                 :       21825 :       sorted_imports.push_back(std::make_pair(p->first, p->second));
    1148                 :       21825 :       seen.insert(p->second);
    1149                 :             :     }
    1150                 :             : 
    1151                 :        4252 :   std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare);
    1152                 :             : 
    1153                 :        4252 :   int package_index = 1;
    1154                 :        4252 :   for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
    1155                 :        4252 :          sorted_imports.begin();
    1156                 :       26077 :        p != sorted_imports.end();
    1157                 :       21825 :        ++p)
    1158                 :             :     {
    1159                 :       21825 :       this->write_c_string("import ");
    1160                 :       21825 :       this->write_string(p->second->package_name());
    1161                 :       21825 :       this->write_c_string(" ");
    1162                 :       21825 :       this->write_string(p->second->pkgpath());
    1163                 :       21825 :       this->write_c_string(" \"");
    1164                 :       21825 :       this->write_string(p->first);
    1165                 :       21825 :       this->write_c_string("\"\n");
    1166                 :             : 
    1167                 :       21825 :       this->packages_[p->second] = package_index;
    1168                 :       21825 :       package_index++;
    1169                 :             :     }
    1170                 :             : 
    1171                 :             :   // Write out a separate list of indirectly imported packages.
    1172                 :        4252 :   std::vector<const Package*> indirect_imports;
    1173                 :       20568 :   for (Unordered_set(const Package*)::const_iterator p =
    1174                 :        4252 :          all_imports.begin();
    1175                 :       20568 :        p != all_imports.end();
    1176                 :       16316 :        ++p)
    1177                 :             :     {
    1178                 :       16316 :       if (seen.find(*p) == seen.end())
    1179                 :        6385 :         indirect_imports.push_back(*p);
    1180                 :             :     }
    1181                 :             : 
    1182                 :        4252 :   std::sort(indirect_imports.begin(), indirect_imports.end(),
    1183                 :             :             packages_compare);
    1184                 :             : 
    1185                 :        4252 :   for (std::vector<const Package*>::const_iterator p =
    1186                 :        4252 :          indirect_imports.begin();
    1187                 :       10637 :        p != indirect_imports.end();
    1188                 :        6385 :        ++p)
    1189                 :             :     {
    1190                 :        6385 :       this->write_c_string("indirectimport ");
    1191                 :        6385 :       this->write_string((*p)->package_name());
    1192                 :        6385 :       this->write_c_string(" ");
    1193                 :        6385 :       this->write_string((*p)->pkgpath());
    1194                 :        6385 :       this->write_c_string("\n");
    1195                 :             : 
    1196                 :        6385 :       this->packages_[*p] = package_index;
    1197                 :        6385 :       package_index++;
    1198                 :             :     }
    1199                 :        4252 : }
    1200                 :             : 
    1201                 :             : void
    1202                 :     1268904 : Export::add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink)
    1203                 :             : {
    1204                 :     1268904 :   Init_graph::iterator it = init_graph->find(src);
    1205                 :     1268904 :   if (it != init_graph->end())
    1206                 :     1179155 :     it->second.insert(sink);
    1207                 :             :   else
    1208                 :             :     {
    1209                 :       89749 :       std::set<unsigned> succs;
    1210                 :       89749 :       succs.insert(sink);
    1211                 :       89749 :       (*init_graph)[src] = succs;
    1212                 :       89749 :     }
    1213                 :     1268904 : }
    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                 :        3549 : 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                 :      162204 :   for (Import_init_set::const_iterator p = imported_init_fns.begin();
    1224                 :      162204 :        p != imported_init_fns.end();
    1225                 :      158655 :        ++p)
    1226                 :             :     {
    1227                 :      158655 :       const Import_init* ii = *p;
    1228                 :      158655 :       if (ii->is_dummy())
    1229                 :       64560 :         continue;
    1230                 :       94095 :       std::map<std::string, unsigned>::const_iterator srcit =
    1231                 :       94095 :           init_idx.find(ii->init_name());
    1232                 :       94095 :       go_assert(srcit != init_idx.end());
    1233                 :       94095 :       unsigned src = srcit->second;
    1234                 :     1313774 :       for (std::set<std::string>::const_iterator pci = ii->precursors().begin();
    1235                 :     1313774 :            pci != ii->precursors().end();
    1236                 :     1219679 :            ++pci)
    1237                 :             :         {
    1238                 :     1219679 :           std::map<std::string, unsigned>::const_iterator it =
    1239                 :     1219679 :               init_idx.find(*pci);
    1240                 :     1219679 :           go_assert(it != init_idx.end());
    1241                 :     1219679 :           unsigned sink = it->second;
    1242                 :     1219679 :           add_init_graph_edge(init_graph, src, sink);
    1243                 :             :         }
    1244                 :             :     }
    1245                 :        3549 : }
    1246                 :             : 
    1247                 :             : // Write out the initialization functions which need to run for this
    1248                 :             : // package.
    1249                 :             : 
    1250                 :             : void
    1251                 :        4252 : 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                 :        4945 :   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                 :        4242 :   std::map<std::string, unsigned> init_idx;
    1259                 :             : 
    1260                 :        4242 :   this->write_c_string("init");
    1261                 :             : 
    1262                 :        4242 :   if (!import_init_fn.empty())
    1263                 :             :     {
    1264                 :        2616 :       this->write_c_string(" ");
    1265                 :        2616 :       this->write_string(package_name);
    1266                 :        2616 :       this->write_c_string(" ");
    1267                 :        2616 :       this->write_string(import_init_fn);
    1268                 :        2616 :       init_idx[import_init_fn] = 0;
    1269                 :             :     }
    1270                 :             : 
    1271                 :        4242 :   if (imported_init_fns.empty())
    1272                 :             :     {
    1273                 :         693 :       this->write_c_string("\n");
    1274                 :         693 :       return;
    1275                 :             :     }
    1276                 :             : 
    1277                 :        3549 :   typedef std::map<int, std::vector<std::string> > level_map;
    1278                 :        3549 :   Init_graph init_graph;
    1279                 :        3549 :   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                 :      162204 :   for (Import_init_set::const_iterator p = imported_init_fns.begin();
    1284                 :      162204 :        p != imported_init_fns.end();
    1285                 :      158655 :        ++p)
    1286                 :             :     {
    1287                 :      158655 :       const Import_init* ii = *p;
    1288                 :             : 
    1289                 :      158655 :       if (ii->init_name() == import_init_fn)
    1290                 :           0 :         continue;
    1291                 :             : 
    1292                 :      158655 :       this->write_c_string(" ");
    1293                 :      158655 :       this->write_string(ii->package_name());
    1294                 :      158655 :       this->write_c_string(" ");
    1295                 :      158655 :       this->write_string(ii->init_name());
    1296                 :             : 
    1297                 :             :       // Populate init_idx.
    1298                 :      158655 :       go_assert(init_idx.find(ii->init_name()) == init_idx.end());
    1299                 :      158655 :       unsigned idx = init_idx.size();
    1300                 :      158655 :       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                 :      158655 :       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                 :        3549 :   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                 :        3549 :   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                 :        3549 :   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                 :       80734 :            ++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                 :        3549 :   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                 :        3549 :   this->write_c_string("init_graph");
    1407                 :       93298 :   for (Init_graph::const_iterator ki = init_graph.begin();
    1408                 :       93298 :        ki != init_graph.end(); ++ki)
    1409                 :             :     {
    1410                 :       89749 :       unsigned src = ki->first;
    1411                 :       89749 :       const std::set<unsigned>& successors = ki->second;
    1412                 :     1358653 :       for (std::set<unsigned>::const_iterator vi = successors.begin();
    1413                 :     1358653 :            vi != successors.end(); ++vi)
    1414                 :             :         {
    1415                 :     1268904 :           this->write_c_string(" ");
    1416                 :     1268904 :           this->write_unsigned(src);
    1417                 :     1268904 :           unsigned sink = (*vi);
    1418                 :     1268904 :           this->write_c_string(" ");
    1419                 :     1268904 :           this->write_unsigned(sink);
    1420                 :             :         }
    1421                 :             :     }
    1422                 :        3549 :   this->write_c_string("\n");
    1423                 :        4242 : }
    1424                 :             : 
    1425                 :             : // Write the types to the export stream.
    1426                 :             : 
    1427                 :             : void
    1428                 :        4252 : Export::write_types(int unexported_type_index)
    1429                 :             : {
    1430                 :             :   // Map from type index to type.
    1431                 :        4252 :   std::vector<const Type*> types(static_cast<size_t>(this->type_index_));
    1432                 :      394725 :   for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
    1433                 :      394725 :        p != this->impl_->type_refs.end();
    1434                 :      390473 :        ++p)
    1435                 :             :     {
    1436                 :      390473 :       if (p->second >= 0)
    1437                 :      233149 :         types.at(p->second) = p->first;
    1438                 :             :     }
    1439                 :             : 
    1440                 :             :   // Write the type information to a buffer.
    1441                 :        4252 :   Stream_to_string type_data;
    1442                 :        4252 :   Export::Stream* orig_stream = this->stream_;
    1443                 :        4252 :   this->stream_ = &type_data;
    1444                 :             : 
    1445                 :        4252 :   std::vector<size_t> type_sizes(static_cast<size_t>(this->type_index_));
    1446                 :        4252 :   type_sizes[0] = 0;
    1447                 :             : 
    1448                 :             :   // Start at 1 because type index 0 is not used.
    1449                 :        4252 :   size_t start_size = 0;
    1450                 :      237401 :   for (int i = 1; i < this->type_index_; ++i)
    1451                 :             :     {
    1452                 :      233149 :       this->write_type_definition(types[i], i);
    1453                 :             : 
    1454                 :      233149 :       size_t cur_size = type_data.string().size();
    1455                 :      233149 :       type_sizes[i] = cur_size - start_size;
    1456                 :      233149 :       start_size = cur_size;
    1457                 :             :     }
    1458                 :             : 
    1459                 :             :   // Back to original stream.
    1460                 :        4252 :   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                 :        4252 :   char buf[100];
    1470                 :        4252 :   snprintf(buf, sizeof buf, "types %d %d", this->type_index_,
    1471                 :             :            unexported_type_index);
    1472                 :        4252 :   this->write_c_string(buf);
    1473                 :             : 
    1474                 :             :   // Start at 1 because type index 0 is not used.
    1475                 :      237401 :   for (int i = 1; i < this->type_index_; ++i)
    1476                 :             :     {
    1477                 :      233149 :       snprintf(buf, sizeof buf, " %lu",
    1478                 :      233149 :                static_cast<unsigned long>(type_sizes[i]));
    1479                 :      233149 :       this->write_c_string(buf);
    1480                 :             :     }
    1481                 :        4252 :   this->write_c_string("\n");
    1482                 :        4252 :   this->write_string(type_data.string());
    1483                 :        4252 : }
    1484                 :             : 
    1485                 :             : // Write a single type to the export stream.
    1486                 :             : 
    1487                 :             : void
    1488                 :      233149 : Export::write_type_definition(const Type* type, int index)
    1489                 :             : {
    1490                 :      233149 :   this->write_c_string("type ");
    1491                 :             : 
    1492                 :      233149 :   char buf[30];
    1493                 :      233149 :   snprintf(buf, sizeof buf, "%d ", index);
    1494                 :      233149 :   this->write_c_string(buf);
    1495                 :             : 
    1496                 :      233149 :   const Named_type* nt = type->named_type();
    1497                 :      233149 :   if (nt != NULL)
    1498                 :             :     {
    1499                 :       76370 :       const Named_object* no = nt->named_object();
    1500                 :       76370 :       const Package* package = no->package();
    1501                 :             : 
    1502                 :       76370 :       this->write_c_string("\"");
    1503                 :       76370 :       if (package != NULL && !Gogo::is_hidden_name(no->name()))
    1504                 :             :         {
    1505                 :       43013 :           this->write_string(package->pkgpath());
    1506                 :       43013 :           this->write_c_string(".");
    1507                 :             :         }
    1508                 :       76370 :       this->write_string(nt->named_object()->name());
    1509                 :       76370 :       this->write_c_string("\" ");
    1510                 :             : 
    1511                 :       76370 :       if (!nt->in_heap())
    1512                 :         509 :         this->write_c_string("notinheap ");
    1513                 :             : 
    1514                 :       76370 :       if (nt->is_alias())
    1515                 :        1276 :         this->write_c_string("= ");
    1516                 :             :     }
    1517                 :             : 
    1518                 :      233149 :   type->export_type(this);
    1519                 :             : 
    1520                 :             :   // Type::export_type will print a newline for a named type, but not
    1521                 :             :   // otherwise.
    1522                 :      233149 :   if (nt == NULL)
    1523                 :      156779 :     this->write_c_string("\n");
    1524                 :      233149 : }
    1525                 :             : 
    1526                 :             : // Write a name to the export stream.
    1527                 :             : 
    1528                 :             : void
    1529                 :      857650 : Export::write_name(const std::string& name)
    1530                 :             : {
    1531                 :      857650 :   if (name.empty())
    1532                 :      102350 :     this->write_c_string("?");
    1533                 :             :   else
    1534                 :      755300 :     this->write_string(Gogo::unpack_hidden_name(name));
    1535                 :      857650 : }
    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                 :     2537808 : Export::write_unsigned(unsigned value)
    1551                 :             : {
    1552                 :     2537808 :   char buf[100];
    1553                 :     2537808 :   snprintf(buf, sizeof buf, "%u", value);
    1554                 :     2537808 :   this->write_c_string(buf);
    1555                 :     2537808 : }
    1556                 :             : 
    1557                 :             : // Return the index of a package.
    1558                 :             : 
    1559                 :             : int
    1560                 :       19277 : Export::package_index(const Package* pkg) const
    1561                 :             : {
    1562                 :       19277 :   Unordered_map(const Package *, int)::const_iterator p =
    1563                 :       19277 :     this->packages_.find(pkg);
    1564                 :       19277 :   go_assert(p != this->packages_.end());
    1565                 :       19277 :   int index = p->second;
    1566                 :       19277 :   go_assert(index != 0);
    1567                 :       19277 :   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                 :     1549431 : Export::type_index(const Type* type)
    1593                 :             : {
    1594                 :     1549431 :   type = type->forwarded();
    1595                 :     1549431 :   Type_refs::const_iterator p = this->impl_->type_refs.find(type);
    1596                 :     1549431 :   go_assert(p != this->impl_->type_refs.end());
    1597                 :     1549431 :   int index = p->second;
    1598                 :     1549431 :   go_assert(index != 0);
    1599                 :     1549431 :   return index;
    1600                 :             : }
    1601                 :             : 
    1602                 :             : // Export a type.
    1603                 :             : 
    1604                 :             : void
    1605                 :     1517966 : Export::write_type(const Type* type)
    1606                 :             : {
    1607                 :     1517966 :   int index = this->type_index(type);
    1608                 :     1517966 :   char buf[30];
    1609                 :     1517966 :   snprintf(buf, sizeof buf, "<type %d>", index);
    1610                 :     1517966 :   this->write_c_string(buf);
    1611                 :     1517966 : }
    1612                 :             : 
    1613                 :             : // Export a type to a function body.
    1614                 :             : 
    1615                 :             : void
    1616                 :       31465 : Export::write_type_to(const Type* type, Export_function_body* efb)
    1617                 :             : {
    1618                 :       31465 :   int index = this->type_index(type);
    1619                 :       31465 :   char buf[30];
    1620                 :       31465 :   snprintf(buf, sizeof buf, "<type %d>", index);
    1621                 :       31465 :   efb->write_c_string(buf);
    1622                 :       31465 : }
    1623                 :             : 
    1624                 :             : // Export escape note.
    1625                 :             : 
    1626                 :             : void
    1627                 :      783270 : Export::write_escape(std::string* note)
    1628                 :             : {
    1629                 :      783270 :   if (note != NULL && *note != "esc:0x0")
    1630                 :             :     {
    1631                 :      327776 :       this->write_c_string(" ");
    1632                 :      327776 :       char buf[50];
    1633                 :      327776 :       go_assert(note->find("esc:") != std::string::npos);
    1634                 :      327776 :       snprintf(buf, sizeof buf, "<%s>", note->c_str());
    1635                 :      327776 :       this->write_c_string(buf);
    1636                 :             :     }
    1637                 :      783270 : }
    1638                 :             : 
    1639                 :             : // Add the builtin types to the export table.
    1640                 :             : 
    1641                 :             : void
    1642                 :        4252 : Export::register_builtin_types(Gogo* gogo)
    1643                 :             : {
    1644                 :        4252 :   this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
    1645                 :        4252 :   this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
    1646                 :        4252 :   this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
    1647                 :        4252 :   this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
    1648                 :        4252 :   this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
    1649                 :        4252 :   this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
    1650                 :        4252 :   this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
    1651                 :        4252 :   this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
    1652                 :        4252 :   this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
    1653                 :        4252 :   this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
    1654                 :        4252 :   this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
    1655                 :        4252 :   this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
    1656                 :        4252 :   this->register_builtin_type(gogo, "int", BUILTIN_INT);
    1657                 :        4252 :   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
    1658                 :        4252 :   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
    1659                 :        4252 :   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
    1660                 :        4252 :   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
    1661                 :        4252 :   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
    1662                 :        4252 :   this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
    1663                 :        4252 :   this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
    1664                 :        4252 :   this->register_builtin_type(gogo, "any", BUILTIN_ANY);
    1665                 :        4252 : }
    1666                 :             : 
    1667                 :             : // Register one builtin type in the export table.
    1668                 :             : 
    1669                 :             : void
    1670                 :       89292 : Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
    1671                 :             : {
    1672                 :       89292 :   Named_object* named_object = gogo->lookup_global(name);
    1673                 :       89292 :   go_assert(named_object != NULL && named_object->is_type());
    1674                 :       89292 :   std::pair<Type_refs::iterator, bool> ins =
    1675                 :       89292 :     this->impl_->type_refs.insert(std::make_pair(named_object->type_value(), code));
    1676                 :       89292 :   go_assert(ins.second);
    1677                 :             : 
    1678                 :             :   // We also insert the underlying type.  We can see the underlying
    1679                 :             :   // type at least for string and bool.  It's OK if this insert
    1680                 :             :   // fails--we expect duplications here, and it doesn't matter when
    1681                 :             :   // they occur.
    1682                 :       89292 :   Type* real_type = named_object->type_value()->real_type();
    1683                 :       89292 :   this->impl_->type_refs.insert(std::make_pair(real_type, code));
    1684                 :       89292 : }
    1685                 :             : 
    1686                 :             : // Class Export::Stream.
    1687                 :             : 
    1688                 :        8504 : Export::Stream::Stream()
    1689                 :             : {
    1690                 :        8504 :   this->sha1_helper_ = go_create_sha1_helper();
    1691                 :        8504 :   go_assert(this->sha1_helper_ != NULL);
    1692                 :        8504 : }
    1693                 :             : 
    1694                 :        8504 : Export::Stream::~Stream()
    1695                 :             : {
    1696                 :        8504 : }
    1697                 :             : 
    1698                 :             : // Write bytes to the stream.  This keeps a checksum of bytes as they
    1699                 :             : // go by.
    1700                 :             : 
    1701                 :             : void
    1702                 :    16235046 : Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
    1703                 :             : {
    1704                 :    16235046 :   this->sha1_helper_->process_bytes(bytes, length);
    1705                 :    16235046 :   this->do_write(bytes, length);
    1706                 :    16235046 : }
    1707                 :             : 
    1708                 :             : // Get the checksum.
    1709                 :             : 
    1710                 :             : std::string
    1711                 :        4252 : Export::Stream::checksum()
    1712                 :             : {
    1713                 :        4252 :   std::string rval = this->sha1_helper_->finish();
    1714                 :        4252 :   delete this->sha1_helper_;
    1715                 :        4252 :   return rval;
    1716                 :             : }
    1717                 :             : 
    1718                 :             : // Write the checksum string to the export data.
    1719                 :             : 
    1720                 :             : void
    1721                 :        4252 : Export::Stream::write_checksum(const std::string& s)
    1722                 :             : {
    1723                 :        4252 :   this->do_write(s.data(), s.length());
    1724                 :        4252 : }
    1725                 :             : 
    1726                 :             : // Class Stream_to_section.
    1727                 :             : 
    1728                 :        4252 : Stream_to_section::Stream_to_section(Backend* backend)
    1729                 :        4252 :     : backend_(backend)
    1730                 :             : {
    1731                 :        4252 : }
    1732                 :             : 
    1733                 :             : // Write data to a section.
    1734                 :             : 
    1735                 :             : void
    1736                 :     7154476 : Stream_to_section::do_write(const char* bytes, size_t length)
    1737                 :             : {
    1738                 :     7154476 :   this->backend_->write_export_data (bytes, length);
    1739                 :     7154476 : }
    1740                 :             : 
    1741                 :             : // Class Export_function_body.
    1742                 :             : 
    1743                 :             : // Record a temporary statement.
    1744                 :             : 
    1745                 :             : unsigned int
    1746                 :        4501 : Export_function_body::record_temporary(const Temporary_statement* temp)
    1747                 :             : {
    1748                 :        4501 :   unsigned int ret = this->next_temporary_index_;
    1749                 :        4501 :   if (ret > 0x7fffffff)
    1750                 :           0 :     go_error_at(temp->location(),
    1751                 :             :                 "too many temporary statements in export data");
    1752                 :        4501 :   ++this->next_temporary_index_;
    1753                 :        4501 :   std::pair<const Temporary_statement*, unsigned int> val(temp, ret);
    1754                 :        4501 :   std::pair<Unordered_map(const Temporary_statement*, unsigned int)::iterator,
    1755                 :        4501 :             bool> ins = this->temporary_indexes_.insert(val);
    1756                 :        4501 :   go_assert(ins.second);
    1757                 :        4501 :   return ret;
    1758                 :             : }
    1759                 :             : 
    1760                 :             : // Return the index of a temporary statement.
    1761                 :             : 
    1762                 :             : unsigned int
    1763                 :        6731 : Export_function_body::temporary_index(const Temporary_statement* temp)
    1764                 :             : {
    1765                 :        6731 :   Unordered_map(const Temporary_statement*, unsigned int)::const_iterator p =
    1766                 :        6731 :     this->temporary_indexes_.find(temp);
    1767                 :        6731 :   go_assert(p != this->temporary_indexes_.end());
    1768                 :        6731 :   return p->second;
    1769                 :             : }
    1770                 :             : 
    1771                 :             : // Return the index of an unnamed label.  If it doesn't already have
    1772                 :             : // an index, give it one.
    1773                 :             : 
    1774                 :             : unsigned int
    1775                 :        3344 : Export_function_body::unnamed_label_index(const Unnamed_label* label)
    1776                 :             : {
    1777                 :        3344 :   unsigned int next = this->next_label_index_;
    1778                 :        3344 :   std::pair<const Unnamed_label*, unsigned int> val(label, next);
    1779                 :        3344 :   std::pair<Unordered_map(const Unnamed_label*, unsigned int)::iterator,
    1780                 :             :             bool> ins =
    1781                 :        3344 :     this->label_indexes_.insert(val);
    1782                 :        3344 :   if (!ins.second)
    1783                 :        1703 :     return ins.first->second;
    1784                 :             :   else
    1785                 :             :     {
    1786                 :        1641 :       if (next > 0x7fffffff)
    1787                 :           0 :         go_error_at(label->location(),
    1788                 :             :                     "too many unnamed labels in export data");
    1789                 :        1641 :       ++this->next_label_index_;
    1790                 :        1641 :       return next;
    1791                 :             :     }
    1792                 :             : }
        

Generated by: LCOV version 2.0-1

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,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.