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