Home | History | Annotate | Download | only in MC
      1 //===- SymbolCategory.cpp -------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include <mcld/MC/SymbolCategory.h>
     10 #include <mcld/LD/LDSymbol.h>
     11 #include <mcld/LD/ResolveInfo.h>
     12 #include <algorithm>
     13 #include <cassert>
     14 
     15 using namespace mcld;
     16 
     17 //===----------------------------------------------------------------------===//
     18 // Category
     19 SymbolCategory::Category::Type
     20 SymbolCategory::Category::categorize(const ResolveInfo& pInfo)
     21 {
     22   if (ResolveInfo::File == pInfo.type())
     23     return Category::File;
     24   if (ResolveInfo::Local == pInfo.binding())
     25     return Category::Local;
     26   if (ResolveInfo::Common == pInfo.desc())
     27     return Category::Common;
     28   if (ResolveInfo::Default   == pInfo.visibility() ||
     29       ResolveInfo::Protected == pInfo.visibility())
     30     return Category::Dynamic;
     31   return Category::Regular;
     32 }
     33 
     34 //===----------------------------------------------------------------------===//
     35 // SymbolCategory
     36 SymbolCategory::SymbolCategory()
     37 {
     38   m_pFile     = new Category(Category::File);
     39   m_pLocal    = new Category(Category::Local);
     40   m_pLocalDyn = new Category(Category::LocalDyn);
     41   m_pCommon   = new Category(Category::Common);
     42   m_pDynamic  = new Category(Category::Dynamic);
     43   m_pRegular  = new Category(Category::Regular);
     44 
     45   m_pFile->next     = m_pLocal;
     46   m_pLocal->next    = m_pLocalDyn;
     47   m_pLocalDyn->next = m_pCommon;
     48   m_pCommon->next   = m_pDynamic;
     49   m_pDynamic->next  = m_pRegular;
     50 
     51   m_pRegular->prev  = m_pDynamic;
     52   m_pDynamic->prev  = m_pCommon;
     53   m_pCommon->prev   = m_pLocalDyn;
     54   m_pLocalDyn->prev = m_pLocal;
     55   m_pLocal->prev    = m_pFile;
     56 }
     57 
     58 SymbolCategory::~SymbolCategory()
     59 {
     60   Category* current = m_pFile;
     61   while (NULL != current) {
     62     Category* tmp = current;
     63     current = current->next;
     64     delete tmp;
     65   }
     66 }
     67 
     68 SymbolCategory& SymbolCategory::add(LDSymbol& pSymbol, Category::Type pTarget)
     69 {
     70   Category* current = m_pRegular;
     71   m_OutputSymbols.push_back(&pSymbol);
     72 
     73   // use non-stable bubble sort to arrange the order of symbols.
     74   while (NULL != current) {
     75     if (current->type == pTarget) {
     76       current->end++;
     77       break;
     78     }
     79     else {
     80       if (!current->empty()) {
     81         std::swap(m_OutputSymbols[current->begin],
     82                   m_OutputSymbols[current->end]);
     83       }
     84       current->end++;
     85       current->begin++;
     86       current = current->prev;
     87     }
     88   }
     89   return *this;
     90 }
     91 
     92 SymbolCategory& SymbolCategory::add(LDSymbol& pSymbol)
     93 {
     94   assert(NULL != pSymbol.resolveInfo());
     95   return add(pSymbol, Category::categorize(*pSymbol.resolveInfo()));
     96 }
     97 
     98 SymbolCategory& SymbolCategory::forceLocal(LDSymbol& pSymbol)
     99 {
    100   return add(pSymbol, Category::Local);
    101 }
    102 
    103 SymbolCategory& SymbolCategory::arrange(LDSymbol& pSymbol,
    104                                         Category::Type pSource,
    105                                         Category::Type pTarget)
    106 {
    107   int distance = pTarget - pSource;
    108   if (0 == distance) {
    109     // in the same category, do not need to re-arrange
    110     return *this;
    111   }
    112 
    113   // source and target are not in the same category
    114   // find the category of source
    115   Category* current = m_pFile;
    116   while(NULL != current) {
    117     if (pSource == current->type)
    118       break;
    119     current = current->next;
    120   }
    121 
    122   assert(NULL != current);
    123   size_t pos = 0;
    124   if (!current->empty()) {
    125     // find the position of source
    126     pos = current->begin;
    127     while (pos != current->end) {
    128       if (m_OutputSymbols[pos] == &pSymbol)
    129         break;
    130       ++pos;
    131     }
    132   }
    133   // FIXME: Try to search the symbol explicitly, if symbol is not in the given
    134   // source category. Or we need to add some logics like shouldForceLocal() in
    135   // SymbolCategory::Category::categorize().
    136   if (current->end == pos || current->empty()) {
    137     current = m_pFile;
    138     do {
    139       pos = current->begin;
    140       while (pos != current->end) {
    141         if (m_OutputSymbols[pos] == &pSymbol) {
    142           distance = pTarget - current->type;
    143           break;
    144         }
    145         ++pos;
    146       }
    147       if (pos != current->end)
    148         break;
    149       current = current->next;
    150     } while (current != NULL);
    151     assert(current != NULL);
    152   }
    153 
    154   // The distance is positive. It means we should bubble sort downward.
    155   if (distance > 0) {
    156     // downward
    157     size_t rear;
    158     do {
    159       if (current->type == pTarget) {
    160         break;
    161       }
    162       else {
    163         assert(!current->isLast() && "target category is wrong.");
    164         rear = current->end - 1;
    165         std::swap(m_OutputSymbols[pos], m_OutputSymbols[rear]);
    166         pos = rear;
    167         current->next->begin--;
    168         current->end--;
    169       }
    170       current = current->next;
    171     } while(NULL != current);
    172 
    173     return *this;
    174   } // downward
    175 
    176   // The distance is negative. It means we should bubble sort upward.
    177   if (distance < 0) {
    178 
    179     // upward
    180     do {
    181       if (current->type == pTarget) {
    182         break;
    183       }
    184       else {
    185         assert(!current->isFirst() && "target category is wrong.");
    186         std::swap(m_OutputSymbols[current->begin], m_OutputSymbols[pos]);
    187         pos = current->begin;
    188         current->begin++;
    189         current->prev->end++;
    190       }
    191       current = current->prev;
    192     } while(NULL != current);
    193 
    194     return *this;
    195   } // upward
    196   return *this;
    197 }
    198 
    199 SymbolCategory& SymbolCategory::arrange(LDSymbol& pSymbol,
    200                                         const ResolveInfo& pSourceInfo)
    201 {
    202   assert(NULL != pSymbol.resolveInfo());
    203   return arrange(pSymbol,
    204                  Category::categorize(pSourceInfo),
    205                  Category::categorize(*pSymbol.resolveInfo()));
    206 }
    207 
    208 SymbolCategory& SymbolCategory::changeCommonsToGlobal()
    209 {
    210   // Change Common to Dynamic/Regular
    211   while (!emptyCommons()) {
    212     size_t pos = m_pCommon->end - 1;
    213     switch (Category::categorize(*(m_OutputSymbols[pos]->resolveInfo()))) {
    214     case Category::Dynamic:
    215       m_pCommon->end--;
    216       m_pDynamic->begin--;
    217       break;
    218     case Category::Regular:
    219       std::swap(m_OutputSymbols[pos], m_OutputSymbols[m_pDynamic->end - 1]);
    220       m_pCommon->end--;
    221       m_pDynamic->begin--;
    222       m_pDynamic->end--;
    223       m_pRegular->begin--;
    224       break;
    225     default:
    226       assert(0);
    227       break;
    228     }
    229   }
    230   return *this;
    231 }
    232 
    233 SymbolCategory& SymbolCategory::changeToDynamic(LDSymbol& pSymbol)
    234 {
    235   assert(NULL != pSymbol.resolveInfo());
    236   return arrange(pSymbol,
    237                  Category::categorize(*pSymbol.resolveInfo()),
    238                  Category::LocalDyn);
    239 }
    240 
    241 size_t SymbolCategory::numOfSymbols() const
    242 {
    243   return m_OutputSymbols.size();
    244 }
    245 
    246 size_t SymbolCategory::numOfFiles() const
    247 {
    248   return m_pFile->size();
    249 }
    250 
    251 size_t SymbolCategory::numOfLocals() const
    252 {
    253   return m_pLocal->size();
    254 }
    255 
    256 size_t SymbolCategory::numOfLocalDyns() const
    257 {
    258   return m_pLocalDyn->size();
    259 }
    260 
    261 size_t SymbolCategory::numOfCommons() const
    262 {
    263   return m_pCommon->size();
    264 }
    265 
    266 size_t SymbolCategory::numOfDynamics() const
    267 {
    268   return m_pDynamic->size();
    269 }
    270 
    271 size_t SymbolCategory::numOfRegulars() const
    272 {
    273   return m_pRegular->size();
    274 }
    275 
    276 bool SymbolCategory::empty() const
    277 {
    278   return m_OutputSymbols.empty();
    279 }
    280 
    281 bool SymbolCategory::emptyFiles() const
    282 {
    283   return m_pFile->empty();
    284 }
    285 
    286 bool SymbolCategory::emptyLocals() const
    287 {
    288   return m_pLocal->empty();
    289 }
    290 
    291 bool SymbolCategory::emptyLocalDyns() const
    292 {
    293   return m_pLocalDyn->empty();
    294 }
    295 
    296 bool SymbolCategory::emptyCommons() const
    297 {
    298   return m_pCommon->empty();
    299 }
    300 
    301 bool SymbolCategory::emptyDynamics() const
    302 {
    303   return m_pDynamic->empty();
    304 }
    305 
    306 bool SymbolCategory::emptyRegulars() const
    307 {
    308   return m_pRegular->empty();
    309 }
    310 
    311 SymbolCategory::iterator SymbolCategory::begin()
    312 {
    313   return m_OutputSymbols.begin();
    314 }
    315 
    316 SymbolCategory::iterator SymbolCategory::end()
    317 {
    318   return m_OutputSymbols.end();
    319 }
    320 
    321 SymbolCategory::const_iterator SymbolCategory::begin() const
    322 {
    323   return m_OutputSymbols.begin();
    324 }
    325 
    326 SymbolCategory::const_iterator SymbolCategory::end() const
    327 {
    328   return m_OutputSymbols.end();
    329 }
    330 
    331 SymbolCategory::iterator SymbolCategory::fileBegin()
    332 {
    333   return m_OutputSymbols.begin();
    334 }
    335 
    336 SymbolCategory::iterator SymbolCategory::fileEnd()
    337 {
    338   iterator iter = fileBegin();
    339   iter += m_pFile->size();
    340   return iter;
    341 }
    342 
    343 SymbolCategory::const_iterator SymbolCategory::fileBegin() const
    344 {
    345   return m_OutputSymbols.begin();
    346 }
    347 
    348 SymbolCategory::const_iterator SymbolCategory::fileEnd() const
    349 {
    350   const_iterator iter = fileBegin();
    351   iter += m_pFile->size();
    352   return iter;
    353 }
    354 
    355 SymbolCategory::iterator SymbolCategory::localBegin()
    356 {
    357   return fileEnd();
    358 }
    359 
    360 SymbolCategory::iterator SymbolCategory::localEnd()
    361 {
    362   iterator iter = localBegin();
    363   iter += m_pLocal->size();
    364   return iter;
    365 }
    366 
    367 SymbolCategory::const_iterator SymbolCategory::localBegin() const
    368 {
    369   return fileEnd();
    370 }
    371 
    372 SymbolCategory::const_iterator SymbolCategory::localEnd() const
    373 {
    374   const_iterator iter = localBegin();
    375   iter += m_pLocal->size();
    376   return iter;
    377 }
    378 
    379 SymbolCategory::iterator SymbolCategory::localDynBegin()
    380 {
    381   return localEnd();
    382 }
    383 
    384 SymbolCategory::iterator SymbolCategory::localDynEnd()
    385 {
    386   iterator iter = localDynBegin();
    387   iter += m_pLocalDyn->size();
    388   return iter;
    389 }
    390 
    391 SymbolCategory::const_iterator SymbolCategory::localDynBegin() const
    392 {
    393   return localEnd();
    394 }
    395 
    396 SymbolCategory::const_iterator SymbolCategory::localDynEnd() const
    397 {
    398   const_iterator iter = localDynBegin();
    399   iter += m_pLocalDyn->size();
    400   return iter;
    401 }
    402 
    403 SymbolCategory::iterator SymbolCategory::commonBegin()
    404 {
    405   return localDynEnd();
    406 }
    407 
    408 SymbolCategory::iterator SymbolCategory::commonEnd()
    409 {
    410   iterator iter = commonBegin();
    411   iter += m_pCommon->size();
    412   return iter;
    413 }
    414 
    415 SymbolCategory::const_iterator SymbolCategory::commonBegin() const
    416 {
    417   return localDynEnd();
    418 }
    419 
    420 SymbolCategory::const_iterator SymbolCategory::commonEnd() const
    421 {
    422   const_iterator iter = commonBegin();
    423   iter += m_pCommon->size();
    424   return iter;
    425 }
    426 
    427 SymbolCategory::iterator SymbolCategory::dynamicBegin()
    428 {
    429   return commonEnd();
    430 }
    431 
    432 SymbolCategory::iterator SymbolCategory::dynamicEnd()
    433 {
    434   iterator iter = dynamicBegin();
    435   iter += m_pDynamic->size();
    436   return iter;
    437 }
    438 
    439 SymbolCategory::const_iterator SymbolCategory::dynamicBegin() const
    440 {
    441   return commonEnd();
    442 }
    443 
    444 SymbolCategory::const_iterator SymbolCategory::dynamicEnd() const
    445 {
    446   const_iterator iter = dynamicBegin();
    447   iter += m_pDynamic->size();
    448   return iter;
    449 }
    450 
    451 SymbolCategory::iterator SymbolCategory::regularBegin()
    452 {
    453   return commonEnd();
    454 }
    455 
    456 SymbolCategory::iterator SymbolCategory::regularEnd()
    457 {
    458   return m_OutputSymbols.end();
    459 }
    460 
    461 SymbolCategory::const_iterator SymbolCategory::regularBegin() const
    462 {
    463   return commonEnd();
    464 }
    465 
    466 SymbolCategory::const_iterator SymbolCategory::regularEnd() const
    467 {
    468   return m_OutputSymbols.end();
    469 }
    470 
    471