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