SymbolCategory.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
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 15using namespace mcld; 16 17//===----------------------------------------------------------------------===// 18// Category 19SymbolCategory::Category::Type 20SymbolCategory::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 36SymbolCategory::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 58SymbolCategory::~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 68SymbolCategory& 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 92SymbolCategory& SymbolCategory::add(LDSymbol& pSymbol) 93{ 94 assert(NULL != pSymbol.resolveInfo()); 95 return add(pSymbol, Category::categorize(*pSymbol.resolveInfo())); 96} 97 98SymbolCategory& SymbolCategory::forceLocal(LDSymbol& pSymbol) 99{ 100 return add(pSymbol, Category::Local); 101} 102 103SymbolCategory& 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 199SymbolCategory& 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 208SymbolCategory& 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 233SymbolCategory& SymbolCategory::changeToDynamic(LDSymbol& pSymbol) 234{ 235 assert(NULL != pSymbol.resolveInfo()); 236 return arrange(pSymbol, 237 Category::categorize(*pSymbol.resolveInfo()), 238 Category::LocalDyn); 239} 240 241size_t SymbolCategory::numOfSymbols() const 242{ 243 return m_OutputSymbols.size(); 244} 245 246size_t SymbolCategory::numOfFiles() const 247{ 248 return m_pFile->size(); 249} 250 251size_t SymbolCategory::numOfLocals() const 252{ 253 return m_pLocal->size(); 254} 255 256size_t SymbolCategory::numOfLocalDyns() const 257{ 258 return m_pLocalDyn->size(); 259} 260 261size_t SymbolCategory::numOfCommons() const 262{ 263 return m_pCommon->size(); 264} 265 266size_t SymbolCategory::numOfDynamics() const 267{ 268 return m_pDynamic->size(); 269} 270 271size_t SymbolCategory::numOfRegulars() const 272{ 273 return m_pRegular->size(); 274} 275 276bool SymbolCategory::empty() const 277{ 278 return m_OutputSymbols.empty(); 279} 280 281bool SymbolCategory::emptyFiles() const 282{ 283 return m_pFile->empty(); 284} 285 286bool SymbolCategory::emptyLocals() const 287{ 288 return m_pLocal->empty(); 289} 290 291bool SymbolCategory::emptyLocalDyns() const 292{ 293 return m_pLocalDyn->empty(); 294} 295 296bool SymbolCategory::emptyCommons() const 297{ 298 return m_pCommon->empty(); 299} 300 301bool SymbolCategory::emptyDynamics() const 302{ 303 return m_pDynamic->empty(); 304} 305 306bool SymbolCategory::emptyRegulars() const 307{ 308 return m_pRegular->empty(); 309} 310 311SymbolCategory::iterator SymbolCategory::begin() 312{ 313 return m_OutputSymbols.begin(); 314} 315 316SymbolCategory::iterator SymbolCategory::end() 317{ 318 return m_OutputSymbols.end(); 319} 320 321SymbolCategory::const_iterator SymbolCategory::begin() const 322{ 323 return m_OutputSymbols.begin(); 324} 325 326SymbolCategory::const_iterator SymbolCategory::end() const 327{ 328 return m_OutputSymbols.end(); 329} 330 331SymbolCategory::iterator SymbolCategory::fileBegin() 332{ 333 return m_OutputSymbols.begin(); 334} 335 336SymbolCategory::iterator SymbolCategory::fileEnd() 337{ 338 iterator iter = fileBegin(); 339 iter += m_pFile->size(); 340 return iter; 341} 342 343SymbolCategory::const_iterator SymbolCategory::fileBegin() const 344{ 345 return m_OutputSymbols.begin(); 346} 347 348SymbolCategory::const_iterator SymbolCategory::fileEnd() const 349{ 350 const_iterator iter = fileBegin(); 351 iter += m_pFile->size(); 352 return iter; 353} 354 355SymbolCategory::iterator SymbolCategory::localBegin() 356{ 357 return fileEnd(); 358} 359 360SymbolCategory::iterator SymbolCategory::localEnd() 361{ 362 iterator iter = localBegin(); 363 iter += m_pLocal->size(); 364 return iter; 365} 366 367SymbolCategory::const_iterator SymbolCategory::localBegin() const 368{ 369 return fileEnd(); 370} 371 372SymbolCategory::const_iterator SymbolCategory::localEnd() const 373{ 374 const_iterator iter = localBegin(); 375 iter += m_pLocal->size(); 376 return iter; 377} 378 379SymbolCategory::iterator SymbolCategory::localDynBegin() 380{ 381 return localEnd(); 382} 383 384SymbolCategory::iterator SymbolCategory::localDynEnd() 385{ 386 iterator iter = localDynBegin(); 387 iter += m_pLocalDyn->size(); 388 return iter; 389} 390 391SymbolCategory::const_iterator SymbolCategory::localDynBegin() const 392{ 393 return localEnd(); 394} 395 396SymbolCategory::const_iterator SymbolCategory::localDynEnd() const 397{ 398 const_iterator iter = localDynBegin(); 399 iter += m_pLocalDyn->size(); 400 return iter; 401} 402 403SymbolCategory::iterator SymbolCategory::commonBegin() 404{ 405 return localDynEnd(); 406} 407 408SymbolCategory::iterator SymbolCategory::commonEnd() 409{ 410 iterator iter = commonBegin(); 411 iter += m_pCommon->size(); 412 return iter; 413} 414 415SymbolCategory::const_iterator SymbolCategory::commonBegin() const 416{ 417 return localDynEnd(); 418} 419 420SymbolCategory::const_iterator SymbolCategory::commonEnd() const 421{ 422 const_iterator iter = commonBegin(); 423 iter += m_pCommon->size(); 424 return iter; 425} 426 427SymbolCategory::iterator SymbolCategory::dynamicBegin() 428{ 429 return commonEnd(); 430} 431 432SymbolCategory::iterator SymbolCategory::dynamicEnd() 433{ 434 iterator iter = dynamicBegin(); 435 iter += m_pDynamic->size(); 436 return iter; 437} 438 439SymbolCategory::const_iterator SymbolCategory::dynamicBegin() const 440{ 441 return commonEnd(); 442} 443 444SymbolCategory::const_iterator SymbolCategory::dynamicEnd() const 445{ 446 const_iterator iter = dynamicBegin(); 447 iter += m_pDynamic->size(); 448 return iter; 449} 450 451SymbolCategory::iterator SymbolCategory::regularBegin() 452{ 453 return commonEnd(); 454} 455 456SymbolCategory::iterator SymbolCategory::regularEnd() 457{ 458 return m_OutputSymbols.end(); 459} 460 461SymbolCategory::const_iterator SymbolCategory::regularBegin() const 462{ 463 return commonEnd(); 464} 465 466SymbolCategory::const_iterator SymbolCategory::regularEnd() const 467{ 468 return m_OutputSymbols.end(); 469} 470 471