• 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,const ResolveInfo & pSourceInfo)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 
changeCommonsToGlobal()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 
changeLocalToDynamic(const LDSymbol & pSymbol)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 
numOfSymbols() const229 size_t SymbolCategory::numOfSymbols() const
230 {
231   return m_OutputSymbols.size();
232 }
233 
numOfFiles() const234 size_t SymbolCategory::numOfFiles() const
235 {
236   return m_pFile->size();
237 }
238 
numOfLocals() const239 size_t SymbolCategory::numOfLocals() const
240 {
241   return m_pLocal->size();
242 }
243 
numOfLocalDyns() const244 size_t SymbolCategory::numOfLocalDyns() const
245 {
246   return m_pLocalDyn->size();
247 }
248 
numOfCommons() const249 size_t SymbolCategory::numOfCommons() const
250 {
251   return m_pCommon->size();
252 }
253 
numOfDynamics() const254 size_t SymbolCategory::numOfDynamics() const
255 {
256   return m_pDynamic->size();
257 }
258 
numOfRegulars() const259 size_t SymbolCategory::numOfRegulars() const
260 {
261   return m_pRegular->size();
262 }
263 
empty() const264 bool SymbolCategory::empty() const
265 {
266   return m_OutputSymbols.empty();
267 }
268 
emptyFiles() const269 bool SymbolCategory::emptyFiles() const
270 {
271   return m_pFile->empty();
272 }
273 
emptyLocals() const274 bool SymbolCategory::emptyLocals() const
275 {
276   return m_pLocal->empty();
277 }
278 
emptyLocalDyns() const279 bool SymbolCategory::emptyLocalDyns() const
280 {
281   return m_pLocalDyn->empty();
282 }
283 
emptyCommons() const284 bool SymbolCategory::emptyCommons() const
285 {
286   return m_pCommon->empty();
287 }
288 
emptyDynamics() const289 bool SymbolCategory::emptyDynamics() const
290 {
291   return m_pDynamic->empty();
292 }
293 
emptyRegulars() const294 bool SymbolCategory::emptyRegulars() const
295 {
296   return m_pRegular->empty();
297 }
298 
begin()299 SymbolCategory::iterator SymbolCategory::begin()
300 {
301   return m_OutputSymbols.begin();
302 }
303 
end()304 SymbolCategory::iterator SymbolCategory::end()
305 {
306   return m_OutputSymbols.end();
307 }
308 
begin() const309 SymbolCategory::const_iterator SymbolCategory::begin() const
310 {
311   return m_OutputSymbols.begin();
312 }
313 
end() const314 SymbolCategory::const_iterator SymbolCategory::end() const
315 {
316   return m_OutputSymbols.end();
317 }
318 
fileBegin()319 SymbolCategory::iterator SymbolCategory::fileBegin()
320 {
321   return m_OutputSymbols.begin();
322 }
323 
fileEnd()324 SymbolCategory::iterator SymbolCategory::fileEnd()
325 {
326   iterator iter = fileBegin();
327   iter += m_pFile->size();
328   return iter;
329 }
330 
fileBegin() const331 SymbolCategory::const_iterator SymbolCategory::fileBegin() const
332 {
333   return m_OutputSymbols.begin();
334 }
335 
fileEnd() const336 SymbolCategory::const_iterator SymbolCategory::fileEnd() const
337 {
338   const_iterator iter = fileBegin();
339   iter += m_pFile->size();
340   return iter;
341 }
342 
localBegin()343 SymbolCategory::iterator SymbolCategory::localBegin()
344 {
345   return fileEnd();
346 }
347 
localEnd()348 SymbolCategory::iterator SymbolCategory::localEnd()
349 {
350   iterator iter = localBegin();
351   iter += m_pLocal->size();
352   return iter;
353 }
354 
localBegin() const355 SymbolCategory::const_iterator SymbolCategory::localBegin() const
356 {
357   return fileEnd();
358 }
359 
localEnd() const360 SymbolCategory::const_iterator SymbolCategory::localEnd() const
361 {
362   const_iterator iter = localBegin();
363   iter += m_pLocal->size();
364   return iter;
365 }
366 
localDynBegin()367 SymbolCategory::iterator SymbolCategory::localDynBegin()
368 {
369   return localEnd();
370 }
371 
localDynEnd()372 SymbolCategory::iterator SymbolCategory::localDynEnd()
373 {
374   iterator iter = localDynBegin();
375   iter += m_pLocalDyn->size();
376   return iter;
377 }
378 
localDynBegin() const379 SymbolCategory::const_iterator SymbolCategory::localDynBegin() const
380 {
381   return localEnd();
382 }
383 
localDynEnd() const384 SymbolCategory::const_iterator SymbolCategory::localDynEnd() const
385 {
386   const_iterator iter = localDynBegin();
387   iter += m_pLocalDyn->size();
388   return iter;
389 }
390 
commonBegin()391 SymbolCategory::iterator SymbolCategory::commonBegin()
392 {
393   return localDynEnd();
394 }
395 
commonEnd()396 SymbolCategory::iterator SymbolCategory::commonEnd()
397 {
398   iterator iter = commonBegin();
399   iter += m_pCommon->size();
400   return iter;
401 }
402 
commonBegin() const403 SymbolCategory::const_iterator SymbolCategory::commonBegin() const
404 {
405   return localDynEnd();
406 }
407 
commonEnd() const408 SymbolCategory::const_iterator SymbolCategory::commonEnd() const
409 {
410   const_iterator iter = commonBegin();
411   iter += m_pCommon->size();
412   return iter;
413 }
414 
dynamicBegin()415 SymbolCategory::iterator SymbolCategory::dynamicBegin()
416 {
417   return commonEnd();
418 }
419 
dynamicEnd()420 SymbolCategory::iterator SymbolCategory::dynamicEnd()
421 {
422   iterator iter = dynamicBegin();
423   iter += m_pDynamic->size();
424   return iter;
425 }
426 
dynamicBegin() const427 SymbolCategory::const_iterator SymbolCategory::dynamicBegin() const
428 {
429   return commonEnd();
430 }
431 
dynamicEnd() const432 SymbolCategory::const_iterator SymbolCategory::dynamicEnd() const
433 {
434   const_iterator iter = dynamicBegin();
435   iter += m_pDynamic->size();
436   return iter;
437 }
438 
regularBegin()439 SymbolCategory::iterator SymbolCategory::regularBegin()
440 {
441   return commonEnd();
442 }
443 
regularEnd()444 SymbolCategory::iterator SymbolCategory::regularEnd()
445 {
446   return m_OutputSymbols.end();
447 }
448 
regularBegin() const449 SymbolCategory::const_iterator SymbolCategory::regularBegin() const
450 {
451   return commonEnd();
452 }
453 
regularEnd() const454 SymbolCategory::const_iterator SymbolCategory::regularEnd() const
455 {
456   return m_OutputSymbols.end();
457 }
458 
459