LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - export.cc (source / functions) Hit Total Coverage
Test: gcc.info Lines: 609 654 93.1 %
Date: 2020-07-04 13:15:35 Functions: 44 46 95.7 %
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                 :    2018942 :   operator()(const Type* type) const
      51                 :            :   {
      52                 :    2018942 :     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                 :    5022245 :   operator()(const Type* t1, const Type* t2) const
      65                 :            :   {
      66                 :    5022245 :     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                 :       3120 : struct Export_impl {
      83                 :            :   Type_refs type_refs;
      84                 :            : };
      85                 :            : 
      86                 :            : // Constructor.
      87                 :            : 
      88                 :       3120 : Export::Export(Stream* stream)
      89                 :       3120 :     : stream_(stream), type_index_(1), packages_(), impl_(new Export_impl)
      90                 :            : {
      91                 :       3120 :   go_assert(Export::checksum_len == Go_sha1_helper::checksum_len);
      92                 :       3120 : }
      93                 :            : 
      94                 :            : // Destructor.
      95                 :            : 
      96                 :       3120 : Export::~Export()
      97                 :            : {
      98                 :       6240 :   delete this->impl_;
      99                 :       3120 : }
     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                 :       3120 :   Collect_export_references(Export* exp,
     109                 :            :                             Unordered_set(Named_object*)* exports,
     110                 :            :                             Unordered_set(const Package*)* imports)
     111                 :       3120 :     : Traverse(traverse_expressions
     112                 :            :                | traverse_types),
     113                 :            :       exp_(exp), exports_(exports), imports_(imports),
     114                 :       3120 :       inline_fcn_worklist_(NULL), exports_finalized_(false)
     115                 :            :   { }
     116                 :            : 
     117                 :            :   // Initial entry point; performs a walk to expand the exports set.
     118                 :            :   void
     119                 :            :   expand_exports(std::vector<Named_object*>* inlinable_functions);
     120                 :            : 
     121                 :            :   // Second entry point (called after the method above), to find
     122                 :            :   // all types referenced by exports.
     123                 :            :   void
     124                 :            :   prepare_types(const std::vector<Named_object*>& sorted_exports);
     125                 :            : 
     126                 :            :  protected:
     127                 :            :   // Override of parent class method.
     128                 :            :   int
     129                 :            :   expression(Expression**);
     130                 :            : 
     131                 :            :   // Override of parent class method.
     132                 :            :   int
     133                 :            :   type(Type* type);
     134                 :            : 
     135                 :            :   // Traverse the components of a function type.
     136                 :            :   void
     137                 :            :   traverse_function_type(Function_type*);
     138                 :            : 
     139                 :            :   // Traverse the methods of a named type, and register its package.
     140                 :            :   void
     141                 :            :   traverse_named_type(Named_type*);
     142                 :            : 
     143                 :            :  private:
     144                 :            : 
     145                 :            :   // Add a named object to the exports set (during expand_exports()).
     146                 :            :   // Returns TRUE if a new object was added to the exports set,
     147                 :            :   // FALSE otherwise.
     148                 :            :   bool
     149                 :            :   add_to_exports(Named_object*);
     150                 :            : 
     151                 :            :   // The exporter.
     152                 :            :   Export* exp_;
     153                 :            :   // The set of named objects to export.
     154                 :            :   Unordered_set(Named_object*)* exports_;
     155                 :            :   // Set containing all directly and indirectly imported packages.
     156                 :            :   Unordered_set(const Package*)* imports_;
     157                 :            :   // Functions we've already traversed and don't need to visit again.
     158                 :            :   Unordered_set(Named_object*) checked_functions_;
     159                 :            :   // Worklist of functions we are exporting with inline bodies that need
     160                 :            :   // to be checked.
     161                 :            :   std::vector<Named_object*>* inline_fcn_worklist_;
     162                 :            :   // Set to true if expand_exports() has been called and is complete.
     163                 :            :   bool exports_finalized_;
     164                 :            : };
     165                 :            : 
     166                 :            : void
     167                 :       3120 : Collect_export_references::expand_exports(std::vector<Named_object*>* fcns)
     168                 :            : {
     169                 :       3120 :   this->inline_fcn_worklist_ = fcns;
     170                 :      43118 :   while (!this->inline_fcn_worklist_->empty())
     171                 :            :     {
     172                 :      39998 :       Named_object* no = this->inline_fcn_worklist_->back();
     173                 :      39998 :       this->inline_fcn_worklist_->pop_back();
     174                 :      39998 :       std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
     175                 :      39998 :         this->checked_functions_.insert(no);
     176                 :      39998 :       if (ins.second)
     177                 :            :         {
     178                 :            :           // This traversal may add new objects to this->exports_ and new
     179                 :            :           // functions to this->inline_fcn_worklist_.
     180                 :      36155 :           no->func_value()->block()->traverse(this);
     181                 :            :         }
     182                 :            :     }
     183                 :       3120 :   this->inline_fcn_worklist_ = NULL;
     184                 :       3120 :   this->exports_finalized_ = true;
     185                 :       3120 : }
     186                 :            : 
     187                 :            : bool
     188                 :      49606 : Collect_export_references::add_to_exports(Named_object* no)
     189                 :            : {
     190                 :      49606 :   std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
     191                 :      49606 :       this->exports_->insert(no);
     192                 :            :   // If the export list has been finalized, then we should not be
     193                 :            :   // adding anything new to the exports set.
     194                 :      49606 :   go_assert(!this->exports_finalized_ || !ins.second);
     195                 :      49606 :   return ins.second;
     196                 :            : }
     197                 :            : 
     198                 :            : int
     199                 :     503013 : Collect_export_references::expression(Expression** pexpr)
     200                 :            : {
     201                 :     503013 :   const Expression* expr = *pexpr;
     202                 :            : 
     203                 :     503013 :   const Var_expression* ve = expr->var_expression();
     204                 :     185436 :   if (ve != NULL)
     205                 :            :     {
     206                 :     185436 :       Named_object* no = ve->named_object();
     207                 :     185436 :       if (no->is_variable() && no->var_value()->is_global())
     208                 :            :         {
     209                 :      20365 :           const Package* var_package = no->package();
     210                 :      20365 :           if (var_package != NULL)
     211                 :       3224 :             this->imports_->insert(var_package);
     212                 :            : 
     213                 :      20365 :           this->add_to_exports(no);
     214                 :      20365 :           no->var_value()->set_is_referenced_by_inline();
     215                 :            :         }
     216                 :     185436 :       return TRAVERSE_CONTINUE;
     217                 :            :     }
     218                 :            : 
     219                 :     317577 :   const Func_expression* fe = expr->func_expression();
     220                 :      52318 :   if (fe != NULL)
     221                 :            :     {
     222                 :      52318 :       Named_object* no = fe->named_object();
     223                 :            : 
     224                 :      52318 :       const Package* func_package = fe->named_object()->package();
     225                 :      52318 :       if (func_package != NULL)
     226                 :      16687 :         this->imports_->insert(func_package);
     227                 :            : 
     228                 :      52318 :       if (no->is_function_declaration()
     229                 :      52318 :           && no->func_declaration_value()->type()->is_builtin())
     230                 :            :         return TRAVERSE_CONTINUE;
     231                 :            : 
     232                 :      38842 :       if (this->inline_fcn_worklist_ != NULL)
     233                 :            :         {
     234                 :      29241 :           bool added = this->add_to_exports(no);
     235                 :            : 
     236                 :      29241 :           if (no->is_function())
     237                 :      16305 :             no->func_value()->set_is_referenced_by_inline();
     238                 :            : 
     239                 :            :           // If 'added' is false then this object was already in
     240                 :            :           // exports_, in which case it was already added to
     241                 :            :           // check_inline_refs_ the first time we added it to exports_, so
     242                 :            :           // we don't need to add it again.
     243                 :      29241 :           if (added
     244                 :      15599 :               && no->is_function()
     245                 :      35574 :               && no->func_value()->export_for_inlining())
     246                 :       3843 :             this->inline_fcn_worklist_->push_back(no);
     247                 :            :         }
     248                 :            : 
     249                 :      38842 :       return TRAVERSE_CONTINUE;
     250                 :            :     }
     251                 :            : 
     252                 :     265259 :   const Named_object* nco = expr->named_constant();
     253                 :     265259 :   if (nco != 0)
     254                 :            :     {
     255                 :      16060 :       const Named_constant *nc = nco->const_value();
     256                 :      16060 :       Type::traverse(nc->type(), this);
     257                 :      16060 :       return TRAVERSE_CONTINUE;
     258                 :            :     }
     259                 :            : 
     260                 :            :   return TRAVERSE_CONTINUE;
     261                 :            : }
     262                 :            : 
     263                 :            : // Collect up the set of types mentioned in things we're exporting, and collect
     264                 :            : // all the packages encountered during type traversal, to make sure we can
     265                 :            : // declare things referered to indirectly (for example, in the body of an
     266                 :            : // exported inline function from another package).
     267                 :            : 
     268                 :            : void
     269                 :       3120 : Collect_export_references::prepare_types(const std::vector<Named_object*>& sorted_exports)
     270                 :            : {
     271                 :            :   // Iterate through the exported objects and traverse any types encountered.
     272                 :     100128 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     273                 :     100128 :        p != sorted_exports.end();
     274                 :     100128 :        ++p)
     275                 :            :     {
     276                 :      97008 :       Named_object* no = *p;
     277                 :      97008 :       switch (no->classification())
     278                 :            :         {
     279                 :      36492 :         case Named_object::NAMED_OBJECT_CONST:
     280                 :      36492 :           {
     281                 :      36492 :             Type* t = no->const_value()->type();
     282                 :      36492 :             if (t != NULL && !t->is_abstract())
     283                 :      14626 :               Type::traverse(t, this);
     284                 :            :           }
     285                 :            :           break;
     286                 :            : 
     287                 :      10196 :         case Named_object::NAMED_OBJECT_TYPE:
     288                 :      10196 :           Type::traverse(no->type_value()->real_type(), this);
     289                 :      10196 :           this->traverse_named_type(no->type_value());
     290                 :      10196 :           break;
     291                 :            : 
     292                 :       7777 :         case Named_object::NAMED_OBJECT_VAR:
     293                 :       7777 :           Type::traverse(no->var_value()->type(), this);
     294                 :       7777 :           break;
     295                 :            : 
     296                 :      32807 :         case Named_object::NAMED_OBJECT_FUNC:
     297                 :      32807 :           {
     298                 :      32807 :             Function* fn = no->func_value();
     299                 :      32807 :             this->traverse_function_type(fn->type());
     300                 :      32807 :             if (fn->export_for_inlining())
     301                 :       8604 :               fn->block()->traverse(this);
     302                 :            :           }
     303                 :            :           break;
     304                 :            : 
     305                 :       9736 :         case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
     306                 :       9736 :           this->traverse_function_type(no->func_declaration_value()->type());
     307                 :       9736 :           break;
     308                 :            : 
     309                 :            :         default:
     310                 :            :           // We shouldn't see anything else.  If we do we'll give an
     311                 :            :           // error later when we try to actually export it.
     312                 :            :           break;
     313                 :            :         }
     314                 :            :     }
     315                 :       3120 : }
     316                 :            : 
     317                 :            : // Record referenced type, record package imports, and make sure we traverse
     318                 :            : // methods of named types.
     319                 :            : 
     320                 :            : int
     321                 :     775517 : Collect_export_references::type(Type* type)
     322                 :            : {
     323                 :            :   // Skip forwarders; don't try to give them a type index.
     324                 :     775517 :   if (type->forward_declaration_type() != NULL)
     325                 :            :     return TRAVERSE_CONTINUE;
     326                 :            : 
     327                 :            :   // Skip the void type, which we'll see when exporting
     328                 :            :   // unsafe.Pointer.  The void type is not itself exported, because
     329                 :            :   // Pointer_type::do_export checks for it.
     330                 :     560944 :   if (type->is_void_type())
     331                 :            :     return TRAVERSE_SKIP_COMPONENTS;
     332                 :            : 
     333                 :            :   // Skip the nil type, turns up in function bodies.
     334                 :     560400 :   if (type->is_nil_type())
     335                 :            :     return TRAVERSE_SKIP_COMPONENTS;
     336                 :            : 
     337                 :            :   // Skip abstract types.  We should never see these in real code,
     338                 :            :   // only in things like const declarations.
     339                 :     557384 :   if (type->is_abstract())
     340                 :            :     return TRAVERSE_SKIP_COMPONENTS;
     341                 :            : 
     342                 :            :   // For interfaces make sure that embedded methods are sorted, since the
     343                 :            :   // comparison function we use for indexing types relies on it (this call has
     344                 :            :   // to happen before the record_type call below).
     345                 :     544571 :   if (type->classification() == Type::TYPE_INTERFACE)
     346                 :            :     {
     347                 :      12963 :       Interface_type* it = type->interface_type();
     348                 :      12963 :       if (it != NULL)
     349                 :      12963 :         it->sort_embedded();
     350                 :            :     }
     351                 :            : 
     352                 :     544571 :   if (!this->exp_->record_type(type))
     353                 :            :     {
     354                 :            :       // We've already seen this type.
     355                 :            :       return TRAVERSE_SKIP_COMPONENTS;
     356                 :            :     }
     357                 :            : 
     358                 :            :   // At this stage of compilation traversing interface types traverses
     359                 :            :   // the final list of methods, but we export the locally defined
     360                 :            :   // methods.  If there is an embedded interface type we need to make
     361                 :            :   // sure to export that.  Check classification, rather than calling
     362                 :            :   // the interface_type method, because we want to handle named types
     363                 :            :   // below.
     364                 :     175652 :   if (type->classification() == Type::TYPE_INTERFACE)
     365                 :            :     {
     366                 :      10218 :       Interface_type* it = type->interface_type();
     367                 :      10218 :       const Typed_identifier_list* methods = it->local_methods();
     368                 :      10218 :       if (methods != NULL)
     369                 :            :         {
     370                 :      38525 :           for (Typed_identifier_list::const_iterator p = methods->begin();
     371                 :      38525 :                p != methods->end();
     372                 :      38525 :                ++p)
     373                 :            :             {
     374                 :      29629 :               if (p->name().empty())
     375                 :       2231 :                 Type::traverse(p->type(), this);
     376                 :            :               else
     377                 :      54796 :                 this->traverse_function_type(p->type()->function_type());
     378                 :            :             }
     379                 :            :         }
     380                 :      10218 :       return TRAVERSE_SKIP_COMPONENTS;
     381                 :            :     }
     382                 :            : 
     383                 :     165434 :   Named_type* nt = type->named_type();
     384                 :     165434 :   if (nt != NULL)
     385                 :      55031 :     this->traverse_named_type(nt);
     386                 :            : 
     387                 :            :   return TRAVERSE_CONTINUE;
     388                 :            : }
     389                 :            : 
     390                 :            : void
     391                 :      65227 : Collect_export_references::traverse_named_type(Named_type* nt)
     392                 :            : {
     393                 :      65227 :   const Package* package = nt->named_object()->package();
     394                 :      65227 :   if (package != NULL)
     395                 :      43065 :     this->imports_->insert(package);
     396                 :            : 
     397                 :            :   // We have to traverse the methods of named types, because we are
     398                 :            :   // going to export them.  This is not done by ordinary type
     399                 :            :   // traversal.
     400                 :      65227 :   const Bindings* methods = nt->local_methods();
     401                 :      65227 :   if (methods != NULL)
     402                 :            :     {
     403                 :      94712 :       for (Bindings::const_definitions_iterator pm =
     404                 :      35381 :              methods->begin_definitions();
     405                 :      94712 :            pm != methods->end_definitions();
     406                 :      94712 :            ++pm)
     407                 :            :         {
     408                 :      59331 :           Function* fn = (*pm)->func_value();
     409                 :      59331 :           this->traverse_function_type(fn->type());
     410                 :      59331 :           if (fn->export_for_inlining())
     411                 :       8631 :             fn->block()->traverse(this);
     412                 :            :         }
     413                 :            : 
     414                 :     300873 :       for (Bindings::const_declarations_iterator pm =
     415                 :      35381 :              methods->begin_declarations();
     416                 :     300873 :            pm != methods->end_declarations();
     417                 :     300873 :            ++pm)
     418                 :            :         {
     419                 :     265492 :           Named_object* mno = pm->second;
     420                 :     265492 :           if (mno->is_function_declaration())
     421                 :     206161 :             this->traverse_function_type(mno->func_declaration_value()->type());
     422                 :            :         }
     423                 :            :     }
     424                 :      65227 : }
     425                 :            : 
     426                 :            : // Traverse the types in a function type.  We don't need the function
     427                 :            : // type itself, just the receiver, parameter, and result types.
     428                 :            : 
     429                 :            : void
     430                 :     335433 : Collect_export_references::traverse_function_type(Function_type* type)
     431                 :            : {
     432                 :     335433 :   go_assert(type != NULL);
     433                 :     335433 :   if (this->remember_type(type))
     434                 :            :     return;
     435                 :     335433 :   const Typed_identifier* receiver = type->receiver();
     436                 :     335433 :   if (receiver != NULL)
     437                 :     265492 :     Type::traverse(receiver->type(), this);
     438                 :     335433 :   const Typed_identifier_list* parameters = type->parameters();
     439                 :     335433 :   if (parameters != NULL)
     440                 :     174500 :     parameters->traverse(this);
     441                 :     335433 :   const Typed_identifier_list* results = type->results();
     442                 :     335433 :   if (results != NULL)
     443                 :     253043 :     results->traverse(this);
     444                 :            : }
     445                 :            : 
     446                 :            : // Return true if we should export NO.
     447                 :            : 
     448                 :            : static bool
     449                 :     390256 : should_export(Named_object* no)
     450                 :            : {
     451                 :            :   // We only export objects which are locally defined.
     452                 :     390256 :   if (no->package() != NULL)
     453                 :            :     return false;
     454                 :            : 
     455                 :            :   // We don't export packages.
     456                 :     366338 :   if (no->is_package())
     457                 :            :     return false;
     458                 :            : 
     459                 :            :   // We don't export hidden names.
     460                 :     332980 :   if (Gogo::is_hidden_name(no->name()))
     461                 :            :     return false;
     462                 :            : 
     463                 :            :   // We don't export various special functions.
     464                 :     140716 :   if (Gogo::is_special_name(no->name()))
     465                 :            :     return false;
     466                 :            : 
     467                 :            :   // Methods are exported with the type, not here.
     468                 :     102221 :   if (no->is_function()
     469                 :     102221 :       && no->func_value()->type()->is_method())
     470                 :            :     return false;
     471                 :      78238 :   if (no->is_function_declaration()
     472                 :      78238 :       && no->func_declaration_value()->type()->is_method())
     473                 :            :     return false;
     474                 :            : 
     475                 :            :   // Don't export dummy global variables created for initializers when
     476                 :            :   // used with sinks.
     477                 :      78238 :   if (no->is_variable() && no->name()[0] == '_' && no->name()[1] == '.')
     478                 :        528 :     return false;
     479                 :            : 
     480                 :            :   return true;
     481                 :            : }
     482                 :            : 
     483                 :            : // A functor to sort Named_object pointers by name.
     484                 :            : 
     485                 :            : struct Sort_bindings
     486                 :            : {
     487                 :            :   bool
     488                 :    1236217 :   operator()(const Named_object* n1, const Named_object* n2) const
     489                 :            :   {
     490                 :    1236217 :     if (n1->package() != n2->package())
     491                 :            :       {
     492                 :     253311 :         if (n1->package() == NULL)
     493                 :            :           return true;
     494                 :     214678 :         if (n2->package() == NULL)
     495                 :            :           return false;
     496                 :     191961 :         return n1->package()->pkgpath() < n2->package()->pkgpath();
     497                 :            :       }
     498                 :            : 
     499                 :     982906 :     return n1->name() < n2->name();
     500                 :            :   }
     501                 :            : };
     502                 :            : 
     503                 :            : // A functor to sort types for export.
     504                 :            : 
     505                 :            : struct Sort_types
     506                 :            : {
     507                 :            :   bool
     508                 :    1474211 :   operator()(const Type* t1, const Type* t2) const
     509                 :            :   {
     510                 :    1474211 :     const Named_type* nt1 = t1->named_type();
     511                 :    1474211 :     const Named_type* nt2 = t2->named_type();
     512                 :    1474211 :     if (nt1 != NULL)
     513                 :            :       {
     514                 :     430648 :         if (nt2 != NULL)
     515                 :            :           {
     516                 :     326955 :             Sort_bindings sb;
     517                 :     326955 :             return sb(nt1->named_object(), nt2->named_object());
     518                 :            :           }
     519                 :            :         else
     520                 :            :           return true;
     521                 :            :       }
     522                 :    1043563 :     else if (nt2 != NULL)
     523                 :            :       return false;
     524                 :     986126 :     if (t1->classification() != t2->classification())
     525                 :     353136 :       return t1->classification() < t2->classification();
     526                 :     632990 :     Gogo* gogo = go_get_gogo();
     527                 :     632990 :     return gogo->type_descriptor_name(t1, NULL).compare(gogo->type_descriptor_name(t2, NULL)) < 0;
     528                 :            :   }
     529                 :            : };
     530                 :            : 
     531                 :            : // Export those identifiers marked for exporting.
     532                 :            : 
     533                 :            : void
     534                 :       3120 : Export::export_globals(const std::string& package_name,
     535                 :            :                        const std::string& prefix,
     536                 :            :                        const std::string& pkgpath,
     537                 :            :                        const std::map<std::string, Package*>& packages,
     538                 :            :                        const std::map<std::string, Package*>& imports,
     539                 :            :                        const std::string& import_init_fn,
     540                 :            :                        const Import_init_set& imported_init_fns,
     541                 :            :                        const Bindings* bindings,
     542                 :            :                        Unordered_set(Named_object*)* functions_marked_inline)
     543                 :            : {
     544                 :            :   // If there have been any errors so far, don't try to export
     545                 :            :   // anything.  That way the export code doesn't have to worry about
     546                 :            :   // mismatched types or other confusions.
     547                 :       3120 :   if (saw_errors())
     548                 :          0 :     return;
     549                 :            : 
     550                 :            :   // EXPORTS is the set of objects to export.  CHECK_INLINE_REFS is a
     551                 :            :   // list of exported function with inline bodies that need to be
     552                 :            :   // checked for references to other objects.  Every function on
     553                 :            :   // CHECK_INLINE_REFS is also on EXPORTS.
     554                 :       6240 :   Unordered_set(Named_object*) exports;
     555                 :       6240 :   std::vector<Named_object*> check_inline_refs;
     556                 :       3120 :   check_inline_refs.reserve(functions_marked_inline->size());
     557                 :            : 
     558                 :            :   // Add all functions/methods from the "marked inlined" set to the
     559                 :            :   // CHECK_INLINE_REFS worklist.
     560                 :      39275 :   for (Unordered_set(Named_object*)::const_iterator p = functions_marked_inline->begin();
     561                 :      39275 :        p != functions_marked_inline->end();
     562                 :      39275 :        ++p)
     563                 :      36155 :       check_inline_refs.push_back(*p);
     564                 :            : 
     565                 :       3120 :   for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
     566                 :     389899 :        p != bindings->end_definitions();
     567                 :     389899 :        ++p)
     568                 :            :     {
     569                 :     386779 :       if (should_export(*p))
     570                 :     386779 :         exports.insert(*p);
     571                 :            :     }
     572                 :            : 
     573                 :       3120 :   for (Bindings::const_declarations_iterator p =
     574                 :       3120 :          bindings->begin_declarations();
     575                 :     296040 :        p != bindings->end_declarations();
     576                 :     296040 :        ++p)
     577                 :            :     {
     578                 :            :       // We export a function declaration as it may be implemented in
     579                 :            :       // supporting C code.  We do not export type declarations.
     580                 :     292920 :       if (p->second->is_function_declaration()
     581                 :     292920 :           && should_export(p->second))
     582                 :     292920 :         exports.insert(p->second);
     583                 :            :     }
     584                 :            : 
     585                 :            :   // Track all imported packages mentioned in export data.
     586                 :       6240 :   Unordered_set(const Package*) all_imports;
     587                 :            : 
     588                 :       6240 :   Collect_export_references collect(this, &exports, &all_imports);
     589                 :            : 
     590                 :            :   // Walk the set of inlinable routine bodies collected above. This
     591                 :            :   // can potentially expand the exports set.
     592                 :       3120 :   collect.expand_exports(&check_inline_refs);
     593                 :            : 
     594                 :            :   // Export the symbols in sorted order.  That will reduce cases where
     595                 :            :   // irrelevant changes to the source code affect the exported
     596                 :            :   // interface.
     597                 :       6240 :   std::vector<Named_object*> sorted_exports;
     598                 :       3120 :   sorted_exports.reserve(exports.size());
     599                 :            : 
     600                 :       3120 :   for (Unordered_set(Named_object*)::const_iterator p = exports.begin();
     601                 :     100128 :        p != exports.end();
     602                 :     100128 :        ++p)
     603                 :            :     {
     604                 :      97008 :       sorted_exports.push_back(*p);
     605                 :            : 
     606                 :      97008 :       const Package* pkg = (*p)->package();
     607                 :      97008 :       if (pkg != NULL)
     608                 :      97008 :         all_imports.insert(pkg);
     609                 :            :     }
     610                 :            : 
     611                 :       3120 :   std::sort(sorted_exports.begin(), sorted_exports.end(), Sort_bindings());
     612                 :            : 
     613                 :            :   // Collect up the set of types mentioned in things we're exporting,
     614                 :            :   // and any packages that may be referred to indirectly.
     615                 :       3120 :   collect.prepare_types(sorted_exports);
     616                 :            : 
     617                 :            :   // Assign indexes to all exported types and types referenced by
     618                 :            :   // things we're exporting.  Return value is index of first non-exported
     619                 :            :   // type.
     620                 :       3120 :   int unexported_type_index = this->assign_type_indices(sorted_exports);
     621                 :            : 
     622                 :            :   // Although the export data is readable, at least this version is,
     623                 :            :   // it is conceptually a binary format.  Start with a four byte
     624                 :            :   // version number.
     625                 :       3120 :   this->write_bytes(Export::cur_magic, Export::magic_len);
     626                 :            : 
     627                 :            :   // The package name.
     628                 :       3120 :   this->write_c_string("package ");
     629                 :       3120 :   this->write_string(package_name);
     630                 :       3120 :   this->write_c_string("\n");
     631                 :            : 
     632                 :            :   // The prefix or package path, used for all global symbols.
     633                 :       3120 :   if (prefix.empty())
     634                 :            :     {
     635                 :       2938 :       go_assert(!pkgpath.empty());
     636                 :       2938 :       this->write_c_string("pkgpath ");
     637                 :       2938 :       this->write_string(pkgpath);
     638                 :            :     }
     639                 :            :   else
     640                 :            :     {
     641                 :        182 :       this->write_c_string("prefix ");
     642                 :        182 :       this->write_string(prefix);
     643                 :            :     }
     644                 :       3120 :   this->write_c_string("\n");
     645                 :            : 
     646                 :       3120 :   this->write_packages(packages);
     647                 :            : 
     648                 :       3120 :   this->write_imports(imports, all_imports);
     649                 :            : 
     650                 :       3120 :   this->write_imported_init_fns(package_name, import_init_fn,
     651                 :            :                                 imported_init_fns);
     652                 :            : 
     653                 :            :   // FIXME: It might be clever to add something about the processor
     654                 :            :   // and ABI being used, although ideally any problems in that area
     655                 :            :   // would be caught by the linker.
     656                 :            : 
     657                 :            :   // Write out all the types, both exported and not.
     658                 :       3120 :   this->write_types(unexported_type_index);
     659                 :            : 
     660                 :            :   // Write out the non-type export data.
     661                 :     100128 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     662                 :     100128 :        p != sorted_exports.end();
     663                 :     100128 :        ++p)
     664                 :            :     {
     665                 :      97008 :       if (!(*p)->is_type())
     666                 :      86812 :         (*p)->export_named_object(this);
     667                 :            :     }
     668                 :            : 
     669                 :       6240 :   std::string checksum = this->stream_->checksum();
     670                 :       6240 :   std::string s = "checksum ";
     671                 :       3120 :   for (std::string::const_iterator p = checksum.begin();
     672                 :      65520 :        p != checksum.end();
     673                 :      65520 :        ++p)
     674                 :            :     {
     675                 :      62400 :       unsigned char c = *p;
     676                 :      62400 :       unsigned int dig = c >> 4;
     677                 :      62400 :       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
     678                 :      62400 :       dig = c & 0xf;
     679                 :     124800 :       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
     680                 :            :     }
     681                 :       3120 :   s += "\n";
     682                 :       3120 :   this->stream_->write_checksum(s);
     683                 :            : }
     684                 :            : 
     685                 :            : // Record a type in the "to be indexed" set. Return true if the type
     686                 :            : // was not already in the set, false otherwise.
     687                 :            : 
     688                 :            : bool
     689                 :     554767 : Export::record_type(Type* type)
     690                 :            : {
     691                 :     554767 :   type = type->forwarded();
     692                 :            : 
     693                 :     554767 :   std::pair<Type_refs::iterator, bool> ins =
     694                 :     554767 :     this->impl_->type_refs.insert(std::make_pair(type, 0));
     695                 :     554767 :   if (!ins.second)
     696                 :            :     {
     697                 :            :       // We've already seen this type.
     698                 :            :       return false;
     699                 :            :     }
     700                 :     178504 :   ins.first->second = 0;
     701                 :            : 
     702                 :     178504 :   return true;
     703                 :            : }
     704                 :            : 
     705                 :            : // Assign the specified type an index.
     706                 :            : 
     707                 :            : void
     708                 :     178504 : Export::set_type_index(const Type* type)
     709                 :            : {
     710                 :     178504 :   type = type->forwarded();
     711                 :     178504 :   std::pair<Type_refs::iterator, bool> ins =
     712                 :     178504 :     this->impl_->type_refs.insert(std::make_pair(type, 0));
     713                 :     178504 :   go_assert(!ins.second);
     714                 :     178504 :   int index = this->type_index_;
     715                 :     178504 :   ++this->type_index_;
     716                 :     178504 :   go_assert(ins.first->second == 0);
     717                 :     178504 :   ins.first->second = index;
     718                 :     178504 : }
     719                 :            : 
     720                 :            : // This helper assigns type indices to all types mentioned directly or
     721                 :            : // indirectly in the things we're exporting. Actual exported types are given
     722                 :            : // indices according to where the appear on the sorted exports list; all other
     723                 :            : // types appear afterwards. Return value is the total number of exported types
     724                 :            : // plus 1, e.g. the index of the 1st non-exported type.
     725                 :            : 
     726                 :            : int
     727                 :       3120 : Export::assign_type_indices(const std::vector<Named_object*>& sorted_exports)
     728                 :            : {
     729                 :            :   // Assign indexes to all the exported types.
     730                 :     100128 :   for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
     731                 :     100128 :        p != sorted_exports.end();
     732                 :     100128 :        ++p)
     733                 :            :     {
     734                 :      97008 :       if (!(*p)->is_type())
     735                 :      86812 :         continue;
     736                 :      10196 :       Interface_type* it = (*p)->type_value()->interface_type();
     737                 :       1175 :       if (it != NULL)
     738                 :       1175 :         it->sort_embedded();
     739                 :      10196 :       this->record_type((*p)->type_value());
     740                 :      10196 :       this->set_type_index((*p)->type_value());
     741                 :            :     }
     742                 :       3120 :   int ret = this->type_index_;
     743                 :            : 
     744                 :            :   // Collect export-referenced, non-builtin types.
     745                 :       3120 :   std::vector<const Type*> types;
     746                 :       3120 :   types.reserve(this->impl_->type_refs.size());
     747                 :     290824 :   for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
     748                 :     290824 :        p != this->impl_->type_refs.end();
     749                 :     290824 :        ++p)
     750                 :            :     {
     751                 :     287704 :       const Type* t = p->first;
     752                 :     287704 :       if (p->second != 0)
     753                 :     119396 :         continue;
     754                 :     168308 :       types.push_back(t);
     755                 :            :     }
     756                 :            : 
     757                 :            :   // Sort the types.
     758                 :       3120 :   std::sort(types.begin(), types.end(), Sort_types());
     759                 :            : 
     760                 :            :   // Assign numbers to the sorted list.
     761                 :     171428 :   for (std::vector<const Type *>::const_iterator p = types.begin();
     762                 :     171428 :        p != types.end();
     763                 :     171428 :        ++p)
     764                 :     168308 :     this->set_type_index((*p));
     765                 :            : 
     766                 :       3120 :   return ret;
     767                 :            : }
     768                 :            : 
     769                 :            : // Sort packages.
     770                 :            : 
     771                 :            : static bool
     772                 :       9559 : packages_compare(const Package* a, const Package* b)
     773                 :            : {
     774                 :       9559 :   if (a->package_name() < b->package_name())
     775                 :            :     return true;
     776                 :       4631 :   else if (a->package_name() > b->package_name())
     777                 :            :     return false;
     778                 :            : 
     779                 :          0 :   if (a->pkgpath() < b->pkgpath())
     780                 :            :     return true;
     781                 :          0 :   else if (a->pkgpath() > b->pkgpath())
     782                 :            :     return false;
     783                 :            : 
     784                 :            :   // In principle if we get here then a == b.  Try to do something sensible
     785                 :            :   // even if the import information is inconsistent.
     786                 :          0 :   if (a->pkgpath_symbol() < b->pkgpath_symbol())
     787                 :            :     return true;
     788                 :          0 :   else if (a->pkgpath_symbol() > b->pkgpath_symbol())
     789                 :            :     return false;
     790                 :            : 
     791                 :          0 :   return a < b;
     792                 :            : }
     793                 :            : 
     794                 :            : // Write out all the known packages whose pkgpath symbol is not a
     795                 :            : // simple transformation of the pkgpath, so that the importing code
     796                 :            : // can reliably know it.
     797                 :            : 
     798                 :            : void
     799                 :       3120 : Export::write_packages(const std::map<std::string, Package*>& packages)
     800                 :            : {
     801                 :            :   // Sort for consistent output.
     802                 :       3120 :   std::vector<Package*> out;
     803                 :      81084 :   for (std::map<std::string, Package*>::const_iterator p = packages.begin();
     804                 :      81084 :        p != packages.end();
     805                 :      81084 :        ++p)
     806                 :            :     {
     807                 :      77964 :       if (p->second->pkgpath_symbol()
     808                 :     155928 :           != Gogo::pkgpath_for_symbol(p->second->pkgpath()))
     809                 :          0 :         out.push_back(p->second);
     810                 :            :     }
     811                 :            : 
     812                 :       3120 :   std::sort(out.begin(), out.end(), packages_compare);
     813                 :            : 
     814                 :       3120 :   for (std::vector<Package*>::const_iterator p = out.begin();
     815                 :       3120 :        p != out.end();
     816                 :       3120 :        ++p)
     817                 :            :     {
     818                 :          0 :       this->write_c_string("package ");
     819                 :          0 :       this->write_string((*p)->package_name());
     820                 :          0 :       this->write_c_string(" ");
     821                 :          0 :       this->write_string((*p)->pkgpath());
     822                 :          0 :       this->write_c_string(" ");
     823                 :          0 :       this->write_string((*p)->pkgpath_symbol());
     824                 :          0 :       this->write_c_string("\n");
     825                 :            :     }
     826                 :       3120 : }
     827                 :            : 
     828                 :            : // Sort imported packages.
     829                 :            : 
     830                 :            : static bool
     831                 :      39915 : import_compare(const std::pair<std::string, Package*>& a,
     832                 :            :                const std::pair<std::string, Package*>& b)
     833                 :            : {
     834                 :      39915 :   return a.first < b.first;
     835                 :            : }
     836                 :            : 
     837                 :            : // Write out the imported packages.
     838                 :            : 
     839                 :            : void
     840                 :       3120 : Export::write_imports(const std::map<std::string, Package*>& imports,
     841                 :            :                       const Unordered_set(const Package*)& all_imports)
     842                 :            : {
     843                 :            :   // Sort the imports for more consistent output.
     844                 :       3120 :   Unordered_set(const Package*) seen;
     845                 :       6240 :   std::vector<std::pair<std::string, Package*> > sorted_imports;
     846                 :       3120 :   for (std::map<std::string, Package*>::const_iterator p = imports.begin();
     847                 :      21387 :        p != imports.end();
     848                 :      21387 :        ++p)
     849                 :            :     {
     850                 :      18267 :       sorted_imports.push_back(std::make_pair(p->first, p->second));
     851                 :      18267 :       seen.insert(p->second);
     852                 :            :     }
     853                 :            : 
     854                 :       3120 :   std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare);
     855                 :            : 
     856                 :       3120 :   int package_index = 1;
     857                 :       3120 :   for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
     858                 :       3120 :          sorted_imports.begin();
     859                 :      21387 :        p != sorted_imports.end();
     860                 :      21387 :        ++p)
     861                 :            :     {
     862                 :      18267 :       this->write_c_string("import ");
     863                 :      18267 :       this->write_string(p->second->package_name());
     864                 :      18267 :       this->write_c_string(" ");
     865                 :      18267 :       this->write_string(p->second->pkgpath());
     866                 :      18267 :       this->write_c_string(" \"");
     867                 :      18267 :       this->write_string(p->first);
     868                 :      18267 :       this->write_c_string("\"\n");
     869                 :            : 
     870                 :      18267 :       this->packages_[p->second] = package_index;
     871                 :      18267 :       package_index++;
     872                 :            :     }
     873                 :            : 
     874                 :            :   // Write out a separate list of indirectly imported packages.
     875                 :       6240 :   std::vector<const Package*> indirect_imports;
     876                 :      16069 :   for (Unordered_set(const Package*)::const_iterator p =
     877                 :       3120 :          all_imports.begin();
     878                 :      16069 :        p != all_imports.end();
     879                 :      16069 :        ++p)
     880                 :            :     {
     881                 :      12949 :       if (seen.find(*p) == seen.end())
     882                 :       4665 :         indirect_imports.push_back(*p);
     883                 :            :     }
     884                 :            : 
     885                 :       3120 :   std::sort(indirect_imports.begin(), indirect_imports.end(),
     886                 :            :             packages_compare);
     887                 :            : 
     888                 :       3120 :   for (std::vector<const Package*>::const_iterator p =
     889                 :       3120 :          indirect_imports.begin();
     890                 :       7785 :        p != indirect_imports.end();
     891                 :       7785 :        ++p)
     892                 :            :     {
     893                 :       4665 :       this->write_c_string("indirectimport ");
     894                 :       4665 :       this->write_string((*p)->package_name());
     895                 :       4665 :       this->write_c_string(" ");
     896                 :       4665 :       this->write_string((*p)->pkgpath());
     897                 :       4665 :       this->write_c_string("\n");
     898                 :            : 
     899                 :       4665 :       this->packages_[*p] = package_index;
     900                 :       4665 :       package_index++;
     901                 :            :     }
     902                 :       3120 : }
     903                 :            : 
     904                 :            : void
     905                 :     927543 : Export::add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink)
     906                 :            : {
     907                 :     927543 :   Init_graph::iterator it = init_graph->find(src);
     908                 :     927543 :   if (it != init_graph->end())
     909                 :     864879 :     it->second.insert(sink);
     910                 :            :   else
     911                 :            :     {
     912                 :     125328 :       std::set<unsigned> succs;
     913                 :      62664 :       succs.insert(sink);
     914                 :      62664 :       (*init_graph)[src] = succs;
     915                 :            :     }
     916                 :     927543 : }
     917                 :            : 
     918                 :            : // Constructs the imported portion of the init graph, e.g. those
     919                 :            : // edges that we read from imported packages.
     920                 :            : 
     921                 :            : void
     922                 :       2801 : Export::populate_init_graph(Init_graph* init_graph,
     923                 :            :                             const Import_init_set& imported_init_fns,
     924                 :            :                             const std::map<std::string, unsigned>& init_idx)
     925                 :            : {
     926                 :     108099 :   for (Import_init_set::const_iterator p = imported_init_fns.begin();
     927                 :     108099 :        p != imported_init_fns.end();
     928                 :     108099 :        ++p)
     929                 :            :     {
     930                 :     105298 :       const Import_init* ii = *p;
     931                 :     105298 :       if (ii->is_dummy())
     932                 :      34702 :         continue;
     933                 :      70596 :       std::map<std::string, unsigned>::const_iterator srcit =
     934                 :      70596 :           init_idx.find(ii->init_name());
     935                 :      70596 :       go_assert(srcit != init_idx.end());
     936                 :      70596 :       unsigned src = srcit->second;
     937                 :     958018 :       for (std::set<std::string>::const_iterator pci = ii->precursors().begin();
     938                 :     958018 :            pci != ii->precursors().end();
     939                 :     958018 :            ++pci)
     940                 :            :         {
     941                 :     887422 :           std::map<std::string, unsigned>::const_iterator it =
     942                 :     887422 :               init_idx.find(*pci);
     943                 :     887422 :           go_assert(it != init_idx.end());
     944                 :     887422 :           unsigned sink = it->second;
     945                 :     887422 :           add_init_graph_edge(init_graph, src, sink);
     946                 :            :         }
     947                 :            :     }
     948                 :       2801 : }
     949                 :            : 
     950                 :            : // Write out the initialization functions which need to run for this
     951                 :            : // package.
     952                 :            : 
     953                 :            : void
     954                 :       3120 : Export::write_imported_init_fns(const std::string& package_name,
     955                 :            :                                 const std::string& import_init_fn,
     956                 :            :                                 const Import_init_set& imported_init_fns)
     957                 :            : {
     958                 :       3120 :   if (import_init_fn.empty() && imported_init_fns.empty()) return;
     959                 :            : 
     960                 :            :   // Maps a given init function to the its index in the exported "init" clause.
     961                 :       5911 :   std::map<std::string, unsigned> init_idx;
     962                 :            : 
     963                 :       3110 :   this->write_c_string("init");
     964                 :            : 
     965                 :       3110 :   if (!import_init_fn.empty())
     966                 :            :     {
     967                 :       1909 :       this->write_c_string(" ");
     968                 :       1909 :       this->write_string(package_name);
     969                 :       1909 :       this->write_c_string(" ");
     970                 :       1909 :       this->write_string(import_init_fn);
     971                 :       1909 :       init_idx[import_init_fn] = 0;
     972                 :            :     }
     973                 :            : 
     974                 :       3110 :   if (imported_init_fns.empty())
     975                 :            :     {
     976                 :        309 :       this->write_c_string("\n");
     977                 :        628 :       return;
     978                 :            :     }
     979                 :            : 
     980                 :       2801 :   typedef std::map<int, std::vector<std::string> > level_map;
     981                 :       5602 :   Init_graph init_graph;
     982                 :       2801 :   level_map inits_at_level;
     983                 :            : 
     984                 :            :   // Walk through the set of import inits (already sorted by
     985                 :            :   // init fcn name) and write them out to the exports.
     986                 :     108099 :   for (Import_init_set::const_iterator p = imported_init_fns.begin();
     987                 :     108099 :        p != imported_init_fns.end();
     988                 :     108099 :        ++p)
     989                 :            :     {
     990                 :     105298 :       const Import_init* ii = *p;
     991                 :            : 
     992                 :     105298 :       if (ii->init_name() == import_init_fn)
     993                 :          0 :         continue;
     994                 :            : 
     995                 :     105298 :       this->write_c_string(" ");
     996                 :     105298 :       this->write_string(ii->package_name());
     997                 :     105298 :       this->write_c_string(" ");
     998                 :     105298 :       this->write_string(ii->init_name());
     999                 :            : 
    1000                 :            :       // Populate init_idx.
    1001                 :     105298 :       go_assert(init_idx.find(ii->init_name()) == init_idx.end());
    1002                 :     105298 :       unsigned idx = init_idx.size();
    1003                 :     105298 :       init_idx[ii->init_name()] = idx;
    1004                 :            : 
    1005                 :            :       // If the init function has a non-negative priority value, this
    1006                 :            :       // is an indication that it was referred to in an older version
    1007                 :            :       // export data section (e.g. we read a legacy object
    1008                 :            :       // file). Record such init fcns so that we can fix up the graph
    1009                 :            :       // for them (handled later in this function).
    1010                 :     105298 :       if (ii->priority() > 0)
    1011                 :            :         {
    1012                 :          0 :           level_map::iterator it = inits_at_level.find(ii->priority());
    1013                 :          0 :           if (it == inits_at_level.end())
    1014                 :            :             {
    1015                 :          0 :               std::vector<std::string> l;
    1016                 :          0 :               l.push_back(ii->init_name());
    1017                 :          0 :               inits_at_level[ii->priority()] = l;
    1018                 :            :             }
    1019                 :            :           else
    1020                 :          0 :             it->second.push_back(ii->init_name());
    1021                 :            :         }
    1022                 :            :     }
    1023                 :       2801 :   this->write_c_string("\n");
    1024                 :            : 
    1025                 :            :   // Create the init graph. Start by populating the graph with
    1026                 :            :   // all the edges we inherited from imported packages.
    1027                 :       2801 :   populate_init_graph(&init_graph, imported_init_fns, init_idx);
    1028                 :            : 
    1029                 :            :   // Now add edges from the local init function to each of the
    1030                 :            :   // imported fcns.
    1031                 :       2801 :   if (!import_init_fn.empty() && import_init_fn[0] != '~')
    1032                 :            :     {
    1033                 :       1208 :       unsigned src = 0;
    1034                 :       1208 :       go_assert(init_idx[import_init_fn] == 0);
    1035                 :      60920 :       for (Import_init_set::const_iterator p = imported_init_fns.begin();
    1036                 :      60920 :            p != imported_init_fns.end();
    1037                 :      60920 :            ++p)
    1038                 :            :         {
    1039                 :      59712 :           const Import_init* ii = *p;
    1040                 :      59712 :           if (ii->is_dummy())
    1041                 :      19591 :             continue;
    1042                 :      40121 :           unsigned sink = init_idx[ii->init_name()];
    1043                 :      40121 :           add_init_graph_edge(&init_graph, src, sink);
    1044                 :            :         }
    1045                 :            :     }
    1046                 :            : 
    1047                 :            :   // In the scenario where one or more of the packages we imported
    1048                 :            :   // was written with the legacy export data format, add dummy edges
    1049                 :            :   // to capture the priority relationships. Here is a package import
    1050                 :            :   // graph as an example:
    1051                 :            :   //
    1052                 :            :   //       *A
    1053                 :            :   //       /|
    1054                 :            :   //      / |
    1055                 :            :   //     B  *C
    1056                 :            :   //       /|
    1057                 :            :   //      / |
    1058                 :            :   //    *D *E
    1059                 :            :   //     | /|
    1060                 :            :   //     |/ |
    1061                 :            :   //    *F  *G
    1062                 :            :   //
    1063                 :            :   // Let's suppose that the object for package "C" is from an old
    1064                 :            :   // gccgo, e.g. it has the old export data format. All other
    1065                 :            :   // packages are compiled with the new compiler and have the new
    1066                 :            :   // format. Packages with *'s have init functions. The scenario is
    1067                 :            :   // that we're compiling a package "A"; during this process we'll
    1068                 :            :   // read the export data for "C". It should look something like
    1069                 :            :   //
    1070                 :            :   //   init F F..import 1 G G..import 1 D D..import 2 E E..import 2;
    1071                 :            :   //
    1072                 :            :   // To capture this information and convey it to the consumers of
    1073                 :            :   // "A", the code below adds edges to the graph from each priority K
    1074                 :            :   // function to every priority K-1 function for appropriate values
    1075                 :            :   // of K. This will potentially add more edges than we need (for
    1076                 :            :   // example, an edge from D to G), but given that we don't expect
    1077                 :            :   // to see large numbers of old objects, this will hopefully be OK.
    1078                 :            : 
    1079                 :       2801 :   if (inits_at_level.size() > 0)
    1080                 :            :     {
    1081                 :          0 :       for (level_map::reverse_iterator it = inits_at_level.rbegin();
    1082                 :          0 :            it != inits_at_level.rend(); ++it)
    1083                 :            :         {
    1084                 :          0 :           int level = it->first;
    1085                 :          0 :           if (level < 2) break;
    1086                 :          0 :           const std::vector<std::string>& fcns_at_level = it->second;
    1087                 :          0 :           for (std::vector<std::string>::const_iterator sit =
    1088                 :          0 :                    fcns_at_level.begin();
    1089                 :          0 :                sit != fcns_at_level.end(); ++sit)
    1090                 :            :             {
    1091                 :          0 :               unsigned src = init_idx[*sit];
    1092                 :          0 :               level_map::iterator it2 = inits_at_level.find(level - 1);
    1093                 :          0 :               if (it2 != inits_at_level.end())
    1094                 :            :                 {
    1095                 :          0 :                   const std::vector<std::string> fcns_at_lm1 = it2->second;
    1096                 :          0 :                   for (std::vector<std::string>::const_iterator mit =
    1097                 :          0 :                            fcns_at_lm1.begin();
    1098                 :          0 :                        mit != fcns_at_lm1.end(); ++mit)
    1099                 :            :                     {
    1100                 :          0 :                       unsigned sink = init_idx[*mit];
    1101                 :          0 :                       add_init_graph_edge(&init_graph, src, sink);
    1102                 :            :                     }
    1103                 :            :                 }
    1104                 :            :             }
    1105                 :            :         }
    1106                 :            :     }
    1107                 :            : 
    1108                 :            :   // Write out the resulting graph.
    1109                 :       2801 :   this->write_c_string("init_graph");
    1110                 :      65465 :   for (Init_graph::const_iterator ki = init_graph.begin();
    1111                 :      65465 :        ki != init_graph.end(); ++ki)
    1112                 :            :     {
    1113                 :      62664 :       unsigned src = ki->first;
    1114                 :      62664 :       const std::set<unsigned>& successors = ki->second;
    1115                 :     990207 :       for (std::set<unsigned>::const_iterator vi = successors.begin();
    1116                 :     990207 :            vi != successors.end(); ++vi)
    1117                 :            :         {
    1118                 :     927543 :           this->write_c_string(" ");
    1119                 :     927543 :           this->write_unsigned(src);
    1120                 :     927543 :           unsigned sink = (*vi);
    1121                 :     927543 :           this->write_c_string(" ");
    1122                 :     927543 :           this->write_unsigned(sink);
    1123                 :            :         }
    1124                 :            :     }
    1125                 :       2801 :   this->write_c_string("\n");
    1126                 :            : }
    1127                 :            : 
    1128                 :            : // Write the types to the export stream.
    1129                 :            : 
    1130                 :            : void
    1131                 :       3120 : Export::write_types(int unexported_type_index)
    1132                 :            : {
    1133                 :            :   // Map from type index to type.
    1134                 :       3120 :   std::vector<const Type*> types(static_cast<size_t>(this->type_index_));
    1135                 :     290824 :   for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
    1136                 :     290824 :        p != this->impl_->type_refs.end();
    1137                 :     290824 :        ++p)
    1138                 :            :     {
    1139                 :     287704 :       if (p->second >= 0)
    1140                 :     178504 :         types.at(p->second) = p->first;
    1141                 :            :     }
    1142                 :            : 
    1143                 :            :   // Write the type information to a buffer.
    1144                 :       6240 :   Stream_to_string type_data;
    1145                 :       3120 :   Export::Stream* orig_stream = this->stream_;
    1146                 :       3120 :   this->stream_ = &type_data;
    1147                 :            : 
    1148                 :       6240 :   std::vector<size_t> type_sizes(static_cast<size_t>(this->type_index_));
    1149                 :       3120 :   type_sizes[0] = 0;
    1150                 :            : 
    1151                 :            :   // Start at 1 because type index 0 is not used.
    1152                 :       3120 :   size_t start_size = 0;
    1153                 :     181624 :   for (int i = 1; i < this->type_index_; ++i)
    1154                 :            :     {
    1155                 :     178504 :       this->write_type_definition(types[i], i);
    1156                 :            : 
    1157                 :     178504 :       size_t cur_size = type_data.string().size();
    1158                 :     178504 :       type_sizes[i] = cur_size - start_size;
    1159                 :     178504 :       start_size = cur_size;
    1160                 :            :     }
    1161                 :            : 
    1162                 :            :   // Back to original stream.
    1163                 :       3120 :   this->stream_ = orig_stream;
    1164                 :            : 
    1165                 :            :   // The line "types MAXP1 EXPORTEDP1 SIZES..." appears before the
    1166                 :            :   // types.  MAXP1 is one more than the maximum type index used; that
    1167                 :            :   // is, it is the size of the array we need to allocate to hold all
    1168                 :            :   // the values.  Indexes 1 up to but not including EXPORTEDP1 are the
    1169                 :            :   // exported types.  The other types are not exported.  SIZES... is a
    1170                 :            :   // list of MAXP1-1 entries listing the size of the type definition
    1171                 :            :   // for each type, starting at index 1.
    1172                 :       3120 :   char buf[100];
    1173                 :       3120 :   snprintf(buf, sizeof buf, "types %d %d", this->type_index_,
    1174                 :            :            unexported_type_index);
    1175                 :       3120 :   this->write_c_string(buf);
    1176                 :            : 
    1177                 :            :   // Start at 1 because type index 0 is not used.
    1178                 :     181624 :   for (int i = 1; i < this->type_index_; ++i)
    1179                 :            :     {
    1180                 :     178504 :       snprintf(buf, sizeof buf, " %lu",
    1181                 :     178504 :                static_cast<unsigned long>(type_sizes[i]));
    1182                 :     178504 :       this->write_c_string(buf);
    1183                 :            :     }
    1184                 :       3120 :   this->write_c_string("\n");
    1185                 :       3120 :   this->write_string(type_data.string());
    1186                 :       3120 : }
    1187                 :            : 
    1188                 :            : // Write a single type to the export stream.
    1189                 :            : 
    1190                 :            : void
    1191                 :     178504 : Export::write_type_definition(const Type* type, int index)
    1192                 :            : {
    1193                 :     178504 :   this->write_c_string("type ");
    1194                 :            : 
    1195                 :     178504 :   char buf[30];
    1196                 :     178504 :   snprintf(buf, sizeof buf, "%d ", index);
    1197                 :     178504 :   this->write_c_string(buf);
    1198                 :            : 
    1199                 :     178504 :   const Named_type* nt = type->named_type();
    1200                 :     178504 :   if (nt != NULL)
    1201                 :            :     {
    1202                 :      57883 :       const Named_object* no = nt->named_object();
    1203                 :      57883 :       const Package* package = no->package();
    1204                 :            : 
    1205                 :      57883 :       this->write_c_string("\"");
    1206                 :      57883 :       if (package != NULL && !Gogo::is_hidden_name(no->name()))
    1207                 :            :         {
    1208                 :      32276 :           this->write_string(package->pkgpath());
    1209                 :      32276 :           this->write_c_string(".");
    1210                 :            :         }
    1211                 :      57883 :       this->write_string(nt->named_object()->name());
    1212                 :      57883 :       this->write_c_string("\" ");
    1213                 :            : 
    1214                 :      57883 :       if (nt->is_alias())
    1215                 :        275 :         this->write_c_string("= ");
    1216                 :            :     }
    1217                 :            : 
    1218                 :     178504 :   type->export_type(this);
    1219                 :            : 
    1220                 :            :   // Type::export_type will print a newline for a named type, but not
    1221                 :            :   // otherwise.
    1222                 :     178504 :   if (nt == NULL)
    1223                 :     120621 :     this->write_c_string("\n");
    1224                 :     178504 : }
    1225                 :            : 
    1226                 :            : // Write a name to the export stream.
    1227                 :            : 
    1228                 :            : void
    1229                 :     645150 : Export::write_name(const std::string& name)
    1230                 :            : {
    1231                 :     645150 :   if (name.empty())
    1232                 :      49938 :     this->write_c_string("?");
    1233                 :            :   else
    1234                 :     595212 :     this->write_string(Gogo::unpack_hidden_name(name));
    1235                 :     645150 : }
    1236                 :            : 
    1237                 :            : // Write an integer value to the export stream.
    1238                 :            : 
    1239                 :            : void
    1240                 :          0 : Export::write_int(int value)
    1241                 :            : {
    1242                 :          0 :   char buf[100];
    1243                 :          0 :   snprintf(buf, sizeof buf, "%d", value);
    1244                 :          0 :   this->write_c_string(buf);
    1245                 :          0 : }
    1246                 :            : 
    1247                 :            : // Write an integer value to the export stream.
    1248                 :            : 
    1249                 :            : void
    1250                 :    1855086 : Export::write_unsigned(unsigned value)
    1251                 :            : {
    1252                 :    1855086 :   char buf[100];
    1253                 :    1855086 :   snprintf(buf, sizeof buf, "%u", value);
    1254                 :    1855086 :   this->write_c_string(buf);
    1255                 :    1855086 : }
    1256                 :            : 
    1257                 :            : // Return the index of a package.
    1258                 :            : 
    1259                 :            : int
    1260                 :      16958 : Export::package_index(const Package* pkg) const
    1261                 :            : {
    1262                 :      16958 :   Unordered_map(const Package *, int)::const_iterator p =
    1263                 :      16958 :     this->packages_.find(pkg);
    1264                 :      16958 :   go_assert(p != this->packages_.end());
    1265                 :      16958 :   int index = p->second;
    1266                 :      16958 :   go_assert(index != 0);
    1267                 :      16958 :   return index;
    1268                 :            : }
    1269                 :            : 
    1270                 :            : // Return the index of a type.
    1271                 :            : 
    1272                 :            : int
    1273                 :    1160871 : Export::type_index(const Type* type)
    1274                 :            : {
    1275                 :    1160871 :   type = type->forwarded();
    1276                 :    1160871 :   Type_refs::const_iterator p = this->impl_->type_refs.find(type);
    1277                 :    1160871 :   go_assert(p != this->impl_->type_refs.end());
    1278                 :    1160871 :   int index = p->second;
    1279                 :    1160871 :   go_assert(index != 0);
    1280                 :    1160871 :   return index;
    1281                 :            : }
    1282                 :            : 
    1283                 :            : // Export a type.
    1284                 :            : 
    1285                 :            : void
    1286                 :    1134825 : Export::write_type(const Type* type)
    1287                 :            : {
    1288                 :    1134825 :   int index = this->type_index(type);
    1289                 :    1134825 :   char buf[30];
    1290                 :    1134825 :   snprintf(buf, sizeof buf, "<type %d>", index);
    1291                 :    1134825 :   this->write_c_string(buf);
    1292                 :    1134825 : }
    1293                 :            : 
    1294                 :            : // Export a type to a function body.
    1295                 :            : 
    1296                 :            : void
    1297                 :      26046 : Export::write_type_to(const Type* type, Export_function_body* efb)
    1298                 :            : {
    1299                 :      26046 :   int index = this->type_index(type);
    1300                 :      26046 :   char buf[30];
    1301                 :      26046 :   snprintf(buf, sizeof buf, "<type %d>", index);
    1302                 :      26046 :   efb->write_c_string(buf);
    1303                 :      26046 : }
    1304                 :            : 
    1305                 :            : // Export escape note.
    1306                 :            : 
    1307                 :            : void
    1308                 :     584297 : Export::write_escape(std::string* note)
    1309                 :            : {
    1310                 :    1077827 :   if (note != NULL && *note != "esc:0x0")
    1311                 :            :     {
    1312                 :     248816 :       this->write_c_string(" ");
    1313                 :     248816 :       char buf[50];
    1314                 :     248816 :       go_assert(note->find("esc:") != std::string::npos);
    1315                 :     248816 :       snprintf(buf, sizeof buf, "<%s>", note->c_str());
    1316                 :     248816 :       this->write_c_string(buf);
    1317                 :            :     }
    1318                 :     584297 : }
    1319                 :            : 
    1320                 :            : // Add the builtin types to the export table.
    1321                 :            : 
    1322                 :            : void
    1323                 :       3120 : Export::register_builtin_types(Gogo* gogo)
    1324                 :            : {
    1325                 :       3120 :   this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
    1326                 :       3120 :   this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
    1327                 :       3120 :   this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
    1328                 :       3120 :   this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
    1329                 :       3120 :   this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
    1330                 :       3120 :   this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
    1331                 :       3120 :   this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
    1332                 :       3120 :   this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
    1333                 :       3120 :   this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
    1334                 :       3120 :   this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
    1335                 :       3120 :   this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
    1336                 :       3120 :   this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
    1337                 :       3120 :   this->register_builtin_type(gogo, "int", BUILTIN_INT);
    1338                 :       3120 :   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
    1339                 :       3120 :   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
    1340                 :       3120 :   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
    1341                 :       3120 :   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
    1342                 :       3120 :   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
    1343                 :       3120 :   this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
    1344                 :       3120 :   this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
    1345                 :       3120 : }
    1346                 :            : 
    1347                 :            : // Register one builtin type in the export table.
    1348                 :            : 
    1349                 :            : void
    1350                 :      62400 : Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
    1351                 :            : {
    1352                 :      62400 :   Named_object* named_object = gogo->lookup_global(name);
    1353                 :      62400 :   go_assert(named_object != NULL && named_object->is_type());
    1354                 :      62400 :   std::pair<Type_refs::iterator, bool> ins =
    1355                 :      62400 :     this->impl_->type_refs.insert(std::make_pair(named_object->type_value(), code));
    1356                 :      62400 :   go_assert(ins.second);
    1357                 :            : 
    1358                 :            :   // We also insert the underlying type.  We can see the underlying
    1359                 :            :   // type at least for string and bool.  It's OK if this insert
    1360                 :            :   // fails--we expect duplications here, and it doesn't matter when
    1361                 :            :   // they occur.
    1362                 :      62400 :   Type* real_type = named_object->type_value()->real_type();
    1363                 :      62400 :   this->impl_->type_refs.insert(std::make_pair(real_type, code));
    1364                 :      62400 : }
    1365                 :            : 
    1366                 :            : // Class Export::Stream.
    1367                 :            : 
    1368                 :       6240 : Export::Stream::Stream()
    1369                 :            : {
    1370                 :       6240 :   this->sha1_helper_ = go_create_sha1_helper();
    1371                 :       6240 :   go_assert(this->sha1_helper_ != NULL);
    1372                 :       6240 : }
    1373                 :            : 
    1374                 :       6240 : Export::Stream::~Stream()
    1375                 :            : {
    1376                 :       6240 : }
    1377                 :            : 
    1378                 :            : // Write bytes to the stream.  This keeps a checksum of bytes as they
    1379                 :            : // go by.
    1380                 :            : 
    1381                 :            : void
    1382                 :   12083678 : Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
    1383                 :            : {
    1384                 :   12083678 :   this->sha1_helper_->process_bytes(bytes, length);
    1385                 :   12083678 :   this->do_write(bytes, length);
    1386                 :   12083678 : }
    1387                 :            : 
    1388                 :            : // Get the checksum.
    1389                 :            : 
    1390                 :            : std::string
    1391                 :       3120 : Export::Stream::checksum()
    1392                 :            : {
    1393                 :       3120 :   std::string rval = this->sha1_helper_->finish();
    1394                 :       3120 :   delete this->sha1_helper_;
    1395                 :       3120 :   return rval;
    1396                 :            : }
    1397                 :            : 
    1398                 :            : // Write the checksum string to the export data.
    1399                 :            : 
    1400                 :            : void
    1401                 :       3120 : Export::Stream::write_checksum(const std::string& s)
    1402                 :            : {
    1403                 :       3120 :   this->do_write(s.data(), s.length());
    1404                 :       3120 : }
    1405                 :            : 
    1406                 :            : // Class Stream_to_section.
    1407                 :            : 
    1408                 :       3120 : Stream_to_section::Stream_to_section(Backend* backend)
    1409                 :       3120 :     : backend_(backend)
    1410                 :            : {
    1411                 :       3120 : }
    1412                 :            : 
    1413                 :            : // Write data to a section.
    1414                 :            : 
    1415                 :            : void
    1416                 :    5369706 : Stream_to_section::do_write(const char* bytes, size_t length)
    1417                 :            : {
    1418                 :    5369706 :   this->backend_->write_export_data (bytes, length);
    1419                 :    5369706 : }
    1420                 :            : 
    1421                 :            : // Class Export_function_body.
    1422                 :            : 
    1423                 :            : // Record a temporary statement.
    1424                 :            : 
    1425                 :            : unsigned int
    1426                 :       3818 : Export_function_body::record_temporary(const Temporary_statement* temp)
    1427                 :            : {
    1428                 :       3818 :   unsigned int ret = this->next_temporary_index_;
    1429                 :       3818 :   if (ret > 0x7fffffff)
    1430                 :          0 :     go_error_at(temp->location(),
    1431                 :            :                 "too many temporary statements in export data");
    1432                 :       3818 :   ++this->next_temporary_index_;
    1433                 :       3818 :   std::pair<const Temporary_statement*, unsigned int> val(temp, ret);
    1434                 :       3818 :   std::pair<Unordered_map(const Temporary_statement*, unsigned int)::iterator,
    1435                 :       3818 :             bool> ins = this->temporary_indexes_.insert(val);
    1436                 :       3818 :   go_assert(ins.second);
    1437                 :       3818 :   return ret;
    1438                 :            : }
    1439                 :            : 
    1440                 :            : // Return the index of a temporary statement.
    1441                 :            : 
    1442                 :            : unsigned int
    1443                 :       5641 : Export_function_body::temporary_index(const Temporary_statement* temp)
    1444                 :            : {
    1445                 :       5641 :   Unordered_map(const Temporary_statement*, unsigned int)::const_iterator p =
    1446                 :       5641 :     this->temporary_indexes_.find(temp);
    1447                 :       5641 :   go_assert(p != this->temporary_indexes_.end());
    1448                 :       5641 :   return p->second;
    1449                 :            : }
    1450                 :            : 
    1451                 :            : // Return the index of an unnamed label.  If it doesn't already have
    1452                 :            : // an index, give it one.
    1453                 :            : 
    1454                 :            : unsigned int
    1455                 :       2779 : Export_function_body::unnamed_label_index(const Unnamed_label* label)
    1456                 :            : {
    1457                 :       2779 :   unsigned int next = this->next_label_index_;
    1458                 :       2779 :   std::pair<const Unnamed_label*, unsigned int> val(label, next);
    1459                 :       2779 :   std::pair<Unordered_map(const Unnamed_label*, unsigned int)::iterator,
    1460                 :            :             bool> ins =
    1461                 :       2779 :     this->label_indexes_.insert(val);
    1462                 :       2779 :   if (!ins.second)
    1463                 :       1410 :     return ins.first->second;
    1464                 :            :   else
    1465                 :            :     {
    1466                 :       1369 :       if (next > 0x7fffffff)
    1467                 :          0 :         go_error_at(label->location(),
    1468                 :            :                     "too many unnamed labels in export data");
    1469                 :       1369 :       ++this->next_label_index_;
    1470                 :       1369 :       return next;
    1471                 :            :     }
    1472                 :            : }

Generated by: LCOV version 1.0

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