blob: 3b770626f6b559cebd073f8806adb7a09a9dc283 [file] [log] [blame]
Michael J. Spencer773a8fb2011-12-18 08:27:59 +00001//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/Core/SymbolTable.h"
11#include "lld/Core/Atom.h"
12#include "lld/Core/File.h"
13#include "lld/Core/InputFiles.h"
14#include "lld/Core/Resolver.h"
15#include "lld/Core/UndefinedAtom.h"
16#include "lld/Platform/Platform.h"
17
18#include "llvm/Support/ErrorHandling.h"
19
20#include <algorithm>
21#include <cassert>
22#include <stdlib.h>
23#include <vector>
24
25namespace lld {
26
27void SymbolTable::add(const Atom &atom) {
28 assert(atom.scope() != Atom::scopeTranslationUnit);
29 switch (atom.combine()) {
30 case Atom::combineNever:
31 case Atom::combineByName:
32 this->addByName(atom);
33 break;
34 case Atom::combineByTypeContent:
35 case Atom::combineByTypeContentDeep:
36 // TO DO: support constants merging
37 break;
38 }
39}
40
41enum NameCollisionResolution {
42 NCR_First,
43 NCR_Second,
44 NCR_Weak,
45 NCR_Larger,
46 NCR_Error
47};
48
49static NameCollisionResolution cases[5][5] = {
50 //regular tentative absolute undef sharedLib
51 {
52 // first is regular
53 NCR_Error, NCR_First, NCR_Error, NCR_First, NCR_First
54 },
55 {
56 // first is tentative
57 NCR_Second, NCR_Larger, NCR_Error, NCR_First, NCR_First
58 },
59 {
60 // first is absolute
61 NCR_Error, NCR_Error, NCR_Error, NCR_First, NCR_First
62 },
63 {
64 // first is undef
65 NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second
66 },
67 {
68 // first is sharedLib
69 NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First
70 }
71};
72
73static NameCollisionResolution collide(Atom::Definition first,
74 Atom::Definition second) {
75 return cases[first][second];
76}
77
78void SymbolTable::addByName(const Atom &atom) {
79 llvm::StringRef name = atom.name();
80 const Atom *existing = this->findByName(name);
81 if (existing == NULL) {
82 // name is not in symbol table yet, add it associate with this atom
83 _nameTable[name] = &atom;
84 } else {
85 // name is already in symbol table and associated with another atom
86 switch (collide(existing->definition(), atom.definition())) {
87 case NCR_First:
88 // using first, just add new to _replacedAtoms
89 _replacedAtoms[&atom] = existing;
90 break;
91 case NCR_Second:
92 // using second, update tables
93 _nameTable[name] = &atom;
94 _replacedAtoms[existing] = &atom;
95 break;
96 default:
97 llvm::report_fatal_error("unhandled switch clause");
98 }
99 }
100}
101
102const Atom *SymbolTable::findByName(llvm::StringRef sym) {
103 NameToAtom::iterator pos = _nameTable.find(sym);
104 if (pos == _nameTable.end())
105 return NULL;
106 return pos->second;
107}
108
109bool SymbolTable::isDefined(llvm::StringRef sym) {
110 const Atom *atom = this->findByName(sym);
111 if (atom == NULL)
112 return false;
113 if (atom->definition() == Atom::definitionUndefined)
114 return false;
115 return true;
116}
117
118const Atom *SymbolTable::replacement(const Atom *atom) {
119 AtomToAtom::iterator pos = _replacedAtoms.find(atom);
120 if (pos == _replacedAtoms.end())
121 return atom;
122 // might be chain, recurse to end
123 return this->replacement(pos->second);
124}
125
126unsigned int SymbolTable::size() {
127 return _nameTable.size();
128}
129
130void SymbolTable::undefines(std::vector<const Atom *> &undefs) {
131 for (NameToAtom::iterator it = _nameTable.begin(),
132 end = _nameTable.end(); it != end; ++it) {
133 const Atom *atom = it->second;
134 assert(atom != NULL);
135 if (atom->definition() == Atom::definitionUndefined)
136 undefs.push_back(atom);
137 }
138}
139
140} // namespace lld