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