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