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                                         const ResolveInfo& pSourceInfo)
    105 {
    106   assert(NULL != pSymbol.resolveInfo());
    107   Category::Type source = Category::categorize(pSourceInfo);
    108   Category::Type target = Category::categorize(*pSymbol.resolveInfo());
    109 
    110   int distance = target - source;
    111   if (0 == distance) {
    112     // in the same category, do not need to re-arrange
    113     return *this;
    114   }
    115 
    116   // source and target are not in the same category
    117   // find the category of source
    118   Category* current = m_pFile;
    119   while(NULL != current) {
    120     if (source == current->type)
    121       break;
    122     current = current->next;
    123   }
    124 
    125   assert(NULL != current);
    126   assert(!current->empty());
    127 
    128   // find the position of source
    129   size_t pos = current->begin;
    130   while (pos != current->end) {
    131     if (m_OutputSymbols[pos] == &pSymbol)
    132       break;
    133     ++pos;
    134   }
    135 
    136   assert(current->end != pos);
    137 
    138   // The distance is positive. It means we should bubble sort downward.
    139   if (distance > 0) {
    140     // downward
    141     size_t rear;
    142     do {
    143       if (current->type == target) {
    144         break;
    145       }
    146       else {
    147         assert(!current->isLast() && "target category is wrong.");
    148         rear = current->end - 1;
    149         std::swap(m_OutputSymbols[pos], m_OutputSymbols[rear]);
    150         pos = rear;
    151         current->next->begin--;
    152         current->end--;
    153       }
    154       current = current->next;
    155     } while(NULL != current);
    156 
    157     return *this;
    158   } // downward
    159 
    160   // The distance is negative. It means we should bubble sort upward.
    161   if (distance < 0) {
    162 
    163     // upward
    164     do {
    165       if (current->type == target) {
    166         break;
    167       }
    168       else {
    169         assert(!current->isFirst() && "target category is wrong.");
    170         std::swap(m_OutputSymbols[current->begin], m_OutputSymbols[pos]);
    171         pos = current->begin;
    172         current->begin++;
    173         current->prev->end++;
    174       }
    175       current = current->prev;
    176     } while(NULL != current);
    177 
    178     return *this;
    179   } // upward
    180   return *this;
    181 }
    182 
    183 SymbolCategory& SymbolCategory::changeCommonsToGlobal()
    184 {
    185   // Change Common to Dynamic/Regular
    186   while (!emptyCommons()) {
    187     size_t pos = m_pCommon->end - 1;
    188     switch (Category::categorize(*(m_OutputSymbols[pos]->resolveInfo()))) {
    189     case Category::Dynamic:
    190       m_pCommon->end--;
    191       m_pDynamic->begin--;
    192       break;
    193     case Category::Regular:
    194       std::swap(m_OutputSymbols[pos], m_OutputSymbols[m_pDynamic->end - 1]);
    195       m_pCommon->end--;
    196       m_pDynamic->begin--;
    197       m_pDynamic->end--;
    198       m_pRegular->begin--;
    199       break;
    200     default:
    201       assert(0);
    202       break;
    203     }
    204   }
    205   return *this;
    206 }
    207 
    208 SymbolCategory& SymbolCategory::changeLocalToDynamic(const LDSymbol& pSymbol)
    209 {
    210   // find the position of pSymbol from local category
    211   size_t pos = m_pLocal->begin;
    212   while (pos != m_pLocal->end) {
    213     if (m_OutputSymbols[pos] == &pSymbol)
    214       break;
    215     ++pos;
    216   }
    217 
    218   // if symbol is not in Local, then do nothing
    219   if (m_pLocal->end == pos)
    220     return *this;
    221 
    222   // bubble sort downward to LocalDyn
    223   std::swap(m_OutputSymbols[pos], m_OutputSymbols[m_pLocal->end - 1]);
    224   m_pLocal->end--;
    225   m_pLocalDyn->begin--;
    226   return *this;
    227 }
    228 
    229 size_t SymbolCategory::numOfSymbols() const
    230 {
    231   return m_OutputSymbols.size();
    232 }
    233 
    234 size_t SymbolCategory::numOfFiles() const
    235 {
    236   return m_pFile->size();
    237 }
    238 
    239 size_t SymbolCategory::numOfLocals() const
    240 {
    241   return m_pLocal->size();
    242 }
    243 
    244 size_t SymbolCategory::numOfLocalDyns() const
    245 {
    246   return m_pLocalDyn->size();
    247 }
    248 
    249 size_t SymbolCategory::numOfCommons() const
    250 {
    251   return m_pCommon->size();
    252 }
    253 
    254 size_t SymbolCategory::numOfDynamics() const
    255 {
    256   return m_pDynamic->size();
    257 }
    258 
    259 size_t SymbolCategory::numOfRegulars() const
    260 {
    261   return m_pRegular->size();
    262 }
    263 
    264 bool SymbolCategory::empty() const
    265 {
    266   return m_OutputSymbols.empty();
    267 }
    268 
    269 bool SymbolCategory::emptyFiles() const
    270 {
    271   return m_pFile->empty();
    272 }
    273 
    274 bool SymbolCategory::emptyLocals() const
    275 {
    276   return m_pLocal->empty();
    277 }
    278 
    279 bool SymbolCategory::emptyLocalDyns() const
    280 {
    281   return m_pLocalDyn->empty();
    282 }
    283 
    284 bool SymbolCategory::emptyCommons() const
    285 {
    286   return m_pCommon->empty();
    287 }
    288 
    289 bool SymbolCategory::emptyDynamics() const
    290 {
    291   return m_pDynamic->empty();
    292 }
    293 
    294 bool SymbolCategory::emptyRegulars() const
    295 {
    296   return m_pRegular->empty();
    297 }
    298 
    299 SymbolCategory::iterator SymbolCategory::begin()
    300 {
    301   return m_OutputSymbols.begin();
    302 }
    303 
    304 SymbolCategory::iterator SymbolCategory::end()
    305 {
    306   return m_OutputSymbols.end();
    307 }
    308 
    309 SymbolCategory::const_iterator SymbolCategory::begin() const
    310 {
    311   return m_OutputSymbols.begin();
    312 }
    313 
    314 SymbolCategory::const_iterator SymbolCategory::end() const
    315 {
    316   return m_OutputSymbols.end();
    317 }
    318 
    319 SymbolCategory::iterator SymbolCategory::fileBegin()
    320 {
    321   return m_OutputSymbols.begin();
    322 }
    323 
    324 SymbolCategory::iterator SymbolCategory::fileEnd()
    325 {
    326   iterator iter = fileBegin();
    327   iter += m_pFile->size();
    328   return iter;
    329 }
    330 
    331 SymbolCategory::const_iterator SymbolCategory::fileBegin() const
    332 {
    333   return m_OutputSymbols.begin();
    334 }
    335 
    336 SymbolCategory::const_iterator SymbolCategory::fileEnd() const
    337 {
    338   const_iterator iter = fileBegin();
    339   iter += m_pFile->size();
    340   return iter;
    341 }
    342 
    343 SymbolCategory::iterator SymbolCategory::localBegin()
    344 {
    345   return fileEnd();
    346 }
    347 
    348 SymbolCategory::iterator SymbolCategory::localEnd()
    349 {
    350   iterator iter = localBegin();
    351   iter += m_pLocal->size();
    352   return iter;
    353 }
    354 
    355 SymbolCategory::const_iterator SymbolCategory::localBegin() const
    356 {
    357   return fileEnd();
    358 }
    359 
    360 SymbolCategory::const_iterator SymbolCategory::localEnd() const
    361 {
    362   const_iterator iter = localBegin();
    363   iter += m_pLocal->size();
    364   return iter;
    365 }
    366 
    367 SymbolCategory::iterator SymbolCategory::localDynBegin()
    368 {
    369   return localEnd();
    370 }
    371 
    372 SymbolCategory::iterator SymbolCategory::localDynEnd()
    373 {
    374   iterator iter = localDynBegin();
    375   iter += m_pLocalDyn->size();
    376   return iter;
    377 }
    378 
    379 SymbolCategory::const_iterator SymbolCategory::localDynBegin() const
    380 {
    381   return localEnd();
    382 }
    383 
    384 SymbolCategory::const_iterator SymbolCategory::localDynEnd() const
    385 {
    386   const_iterator iter = localDynBegin();
    387   iter += m_pLocalDyn->size();
    388   return iter;
    389 }
    390 
    391 SymbolCategory::iterator SymbolCategory::commonBegin()
    392 {
    393   return localDynEnd();
    394 }
    395 
    396 SymbolCategory::iterator SymbolCategory::commonEnd()
    397 {
    398   iterator iter = commonBegin();
    399   iter += m_pCommon->size();
    400   return iter;
    401 }
    402 
    403 SymbolCategory::const_iterator SymbolCategory::commonBegin() const
    404 {
    405   return localDynEnd();
    406 }
    407 
    408 SymbolCategory::const_iterator SymbolCategory::commonEnd() const
    409 {
    410   const_iterator iter = commonBegin();
    411   iter += m_pCommon->size();
    412   return iter;
    413 }
    414 
    415 SymbolCategory::iterator SymbolCategory::dynamicBegin()
    416 {
    417   return commonEnd();
    418 }
    419 
    420 SymbolCategory::iterator SymbolCategory::dynamicEnd()
    421 {
    422   iterator iter = dynamicBegin();
    423   iter += m_pDynamic->size();
    424   return iter;
    425 }
    426 
    427 SymbolCategory::const_iterator SymbolCategory::dynamicBegin() const
    428 {
    429   return commonEnd();
    430 }
    431 
    432 SymbolCategory::const_iterator SymbolCategory::dynamicEnd() const
    433 {
    434   const_iterator iter = dynamicBegin();
    435   iter += m_pDynamic->size();
    436   return iter;
    437 }
    438 
    439 SymbolCategory::iterator SymbolCategory::regularBegin()
    440 {
    441   return commonEnd();
    442 }
    443 
    444 SymbolCategory::iterator SymbolCategory::regularEnd()
    445 {
    446   return m_OutputSymbols.end();
    447 }
    448 
    449 SymbolCategory::const_iterator SymbolCategory::regularBegin() const
    450 {
    451   return commonEnd();
    452 }
    453 
    454 SymbolCategory::const_iterator SymbolCategory::regularEnd() const
    455 {
    456   return m_OutputSymbols.end();
    457 }
    458 
    459