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