LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - export.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.9 % 840 738
Test Date: 2026-02-28 14:20:25 Functions: 93.9 % 49 46
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

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