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