• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
categorize(const ResolveInfo & pInfo)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
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 
~SymbolCategory()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 
add(LDSymbol & pSymbol,Category::Type pTarget)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 
add(LDSymbol & pSymbol)92 SymbolCategory& SymbolCategory::add(LDSymbol& pSymbol)
93 {
94   assert(NULL != pSymbol.resolveInfo());
95   return add(pSymbol, Category::categorize(*pSymbol.resolveInfo()));
96 }
97 
forceLocal(LDSymbol & pSymbol)98 SymbolCategory& SymbolCategory::forceLocal(LDSymbol& pSymbol)
99 {
100   return add(pSymbol, Category::Local);
101 }
102 
arrange(LDSymbol & pSymbol,Category::Type pSource,Category::Type pTarget)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   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 
arrange(LDSymbol & pSymbol,const ResolveInfo & pSourceInfo)199 SymbolCategory& 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 
changeCommonsToGlobal()208 SymbolCategory& 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 
changeToDynamic(LDSymbol & pSymbol)233 SymbolCategory& SymbolCategory::changeToDynamic(LDSymbol& pSymbol)
234 {
235   assert(NULL != pSymbol.resolveInfo());
236   return arrange(pSymbol,
237                  Category::categorize(*pSymbol.resolveInfo()),
238                  Category::LocalDyn);
239 }
240 
numOfSymbols() const241 size_t SymbolCategory::numOfSymbols() const
242 {
243   return m_OutputSymbols.size();
244 }
245 
numOfFiles() const246 size_t SymbolCategory::numOfFiles() const
247 {
248   return m_pFile->size();
249 }
250 
numOfLocals() const251 size_t SymbolCategory::numOfLocals() const
252 {
253   return m_pLocal->size();
254 }
255 
numOfLocalDyns() const256 size_t SymbolCategory::numOfLocalDyns() const
257 {
258   return m_pLocalDyn->size();
259 }
260 
numOfCommons() const261 size_t SymbolCategory::numOfCommons() const
262 {
263   return m_pCommon->size();
264 }
265 
numOfDynamics() const266 size_t SymbolCategory::numOfDynamics() const
267 {
268   return m_pDynamic->size();
269 }
270 
numOfRegulars() const271 size_t SymbolCategory::numOfRegulars() const
272 {
273   return m_pRegular->size();
274 }
275 
empty() const276 bool SymbolCategory::empty() const
277 {
278   return m_OutputSymbols.empty();
279 }
280 
emptyFiles() const281 bool SymbolCategory::emptyFiles() const
282 {
283   return m_pFile->empty();
284 }
285 
emptyLocals() const286 bool SymbolCategory::emptyLocals() const
287 {
288   return m_pLocal->empty();
289 }
290 
emptyLocalDyns() const291 bool SymbolCategory::emptyLocalDyns() const
292 {
293   return m_pLocalDyn->empty();
294 }
295 
emptyCommons() const296 bool SymbolCategory::emptyCommons() const
297 {
298   return m_pCommon->empty();
299 }
300 
emptyDynamics() const301 bool SymbolCategory::emptyDynamics() const
302 {
303   return m_pDynamic->empty();
304 }
305 
emptyRegulars() const306 bool SymbolCategory::emptyRegulars() const
307 {
308   return m_pRegular->empty();
309 }
310 
begin()311 SymbolCategory::iterator SymbolCategory::begin()
312 {
313   return m_OutputSymbols.begin();
314 }
315 
end()316 SymbolCategory::iterator SymbolCategory::end()
317 {
318   return m_OutputSymbols.end();
319 }
320 
begin() const321 SymbolCategory::const_iterator SymbolCategory::begin() const
322 {
323   return m_OutputSymbols.begin();
324 }
325 
end() const326 SymbolCategory::const_iterator SymbolCategory::end() const
327 {
328   return m_OutputSymbols.end();
329 }
330 
fileBegin()331 SymbolCategory::iterator SymbolCategory::fileBegin()
332 {
333   return m_OutputSymbols.begin();
334 }
335 
fileEnd()336 SymbolCategory::iterator SymbolCategory::fileEnd()
337 {
338   iterator iter = fileBegin();
339   iter += m_pFile->size();
340   return iter;
341 }
342 
fileBegin() const343 SymbolCategory::const_iterator SymbolCategory::fileBegin() const
344 {
345   return m_OutputSymbols.begin();
346 }
347 
fileEnd() const348 SymbolCategory::const_iterator SymbolCategory::fileEnd() const
349 {
350   const_iterator iter = fileBegin();
351   iter += m_pFile->size();
352   return iter;
353 }
354 
localBegin()355 SymbolCategory::iterator SymbolCategory::localBegin()
356 {
357   return fileEnd();
358 }
359 
localEnd()360 SymbolCategory::iterator SymbolCategory::localEnd()
361 {
362   iterator iter = localBegin();
363   iter += m_pLocal->size();
364   return iter;
365 }
366 
localBegin() const367 SymbolCategory::const_iterator SymbolCategory::localBegin() const
368 {
369   return fileEnd();
370 }
371 
localEnd() const372 SymbolCategory::const_iterator SymbolCategory::localEnd() const
373 {
374   const_iterator iter = localBegin();
375   iter += m_pLocal->size();
376   return iter;
377 }
378 
localDynBegin()379 SymbolCategory::iterator SymbolCategory::localDynBegin()
380 {
381   return localEnd();
382 }
383 
localDynEnd()384 SymbolCategory::iterator SymbolCategory::localDynEnd()
385 {
386   iterator iter = localDynBegin();
387   iter += m_pLocalDyn->size();
388   return iter;
389 }
390 
localDynBegin() const391 SymbolCategory::const_iterator SymbolCategory::localDynBegin() const
392 {
393   return localEnd();
394 }
395 
localDynEnd() const396 SymbolCategory::const_iterator SymbolCategory::localDynEnd() const
397 {
398   const_iterator iter = localDynBegin();
399   iter += m_pLocalDyn->size();
400   return iter;
401 }
402 
commonBegin()403 SymbolCategory::iterator SymbolCategory::commonBegin()
404 {
405   return localDynEnd();
406 }
407 
commonEnd()408 SymbolCategory::iterator SymbolCategory::commonEnd()
409 {
410   iterator iter = commonBegin();
411   iter += m_pCommon->size();
412   return iter;
413 }
414 
commonBegin() const415 SymbolCategory::const_iterator SymbolCategory::commonBegin() const
416 {
417   return localDynEnd();
418 }
419 
commonEnd() const420 SymbolCategory::const_iterator SymbolCategory::commonEnd() const
421 {
422   const_iterator iter = commonBegin();
423   iter += m_pCommon->size();
424   return iter;
425 }
426 
dynamicBegin()427 SymbolCategory::iterator SymbolCategory::dynamicBegin()
428 {
429   return commonEnd();
430 }
431 
dynamicEnd()432 SymbolCategory::iterator SymbolCategory::dynamicEnd()
433 {
434   iterator iter = dynamicBegin();
435   iter += m_pDynamic->size();
436   return iter;
437 }
438 
dynamicBegin() const439 SymbolCategory::const_iterator SymbolCategory::dynamicBegin() const
440 {
441   return commonEnd();
442 }
443 
dynamicEnd() const444 SymbolCategory::const_iterator SymbolCategory::dynamicEnd() const
445 {
446   const_iterator iter = dynamicBegin();
447   iter += m_pDynamic->size();
448   return iter;
449 }
450 
regularBegin()451 SymbolCategory::iterator SymbolCategory::regularBegin()
452 {
453   return commonEnd();
454 }
455 
regularEnd()456 SymbolCategory::iterator SymbolCategory::regularEnd()
457 {
458   return m_OutputSymbols.end();
459 }
460 
regularBegin() const461 SymbolCategory::const_iterator SymbolCategory::regularBegin() const
462 {
463   return commonEnd();
464 }
465 
regularEnd() const466 SymbolCategory::const_iterator SymbolCategory::regularEnd() const
467 {
468   return m_OutputSymbols.end();
469 }
470 
471