blob: ebd4c0bde5010f627068b448c9acac07b9896441 [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);
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000029 if ( !atom.internalName() ) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000030 this->addByName(atom);
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000031 }
32 else if ( atom.mergeDuplicates() ) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000033 // TO DO: support constants merging
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000034 }
35}
36
37enum NameCollisionResolution {
38 NCR_First,
39 NCR_Second,
40 NCR_Weak,
41 NCR_Larger,
42 NCR_Error
43};
44
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000045static NameCollisionResolution cases[6][6] = {
46 //regular weak tentative absolute undef sharedLib
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000047 {
48 // first is regular
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000049 NCR_Error, NCR_First, NCR_First, NCR_Error, NCR_First, NCR_First
50 },
51 {
52 // first is weak
53 NCR_Second, NCR_Weak, NCR_Larger, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000054 },
55 {
56 // first is tentative
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000057 NCR_Second, NCR_Second, NCR_Larger, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000058 },
59 {
60 // first is absolute
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000061 NCR_Error, NCR_Error, NCR_Error, NCR_Error, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000062 },
63 {
64 // first is undef
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000065 NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000066 },
67 {
68 // first is sharedLib
Nick Kledzikf96d0ad2011-12-20 02:18:44 +000069 NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000070 }
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