summaryrefslogtreecommitdiffstats
path: root/lld/lib/Core/SymbolTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/Core/SymbolTable.cpp')
-rw-r--r--lld/lib/Core/SymbolTable.cpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp
new file mode 100644
index 00000000000..3b770626f6b
--- /dev/null
+++ b/lld/lib/Core/SymbolTable.cpp
@@ -0,0 +1,140 @@
+//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Core/SymbolTable.h"
+#include "lld/Core/Atom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/InputFiles.h"
+#include "lld/Core/Resolver.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Platform/Platform.h"
+
+#include "llvm/Support/ErrorHandling.h"
+
+#include <algorithm>
+#include <cassert>
+#include <stdlib.h>
+#include <vector>
+
+namespace lld {
+
+void SymbolTable::add(const Atom &atom) {
+ assert(atom.scope() != Atom::scopeTranslationUnit);
+ switch (atom.combine()) {
+ case Atom::combineNever:
+ case Atom::combineByName:
+ this->addByName(atom);
+ break;
+ case Atom::combineByTypeContent:
+ case Atom::combineByTypeContentDeep:
+ // TO DO: support constants merging
+ break;
+ }
+}
+
+enum NameCollisionResolution {
+ NCR_First,
+ NCR_Second,
+ NCR_Weak,
+ NCR_Larger,
+ NCR_Error
+};
+
+static NameCollisionResolution cases[5][5] = {
+ //regular tentative absolute undef sharedLib
+ {
+ // first is regular
+ NCR_Error, NCR_First, NCR_Error, NCR_First, NCR_First
+ },
+ {
+ // first is tentative
+ NCR_Second, NCR_Larger, NCR_Error, NCR_First, NCR_First
+ },
+ {
+ // first is absolute
+ NCR_Error, NCR_Error, NCR_Error, NCR_First, NCR_First
+ },
+ {
+ // first is undef
+ NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second
+ },
+ {
+ // first is sharedLib
+ NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First
+ }
+};
+
+static NameCollisionResolution collide(Atom::Definition first,
+ Atom::Definition second) {
+ return cases[first][second];
+}
+
+void SymbolTable::addByName(const Atom &atom) {
+ llvm::StringRef name = atom.name();
+ const Atom *existing = this->findByName(name);
+ if (existing == NULL) {
+ // name is not in symbol table yet, add it associate with this atom
+ _nameTable[name] = &atom;
+ } else {
+ // name is already in symbol table and associated with another atom
+ switch (collide(existing->definition(), atom.definition())) {
+ case NCR_First:
+ // using first, just add new to _replacedAtoms
+ _replacedAtoms[&atom] = existing;
+ break;
+ case NCR_Second:
+ // using second, update tables
+ _nameTable[name] = &atom;
+ _replacedAtoms[existing] = &atom;
+ break;
+ default:
+ llvm::report_fatal_error("unhandled switch clause");
+ }
+ }
+}
+
+const Atom *SymbolTable::findByName(llvm::StringRef sym) {
+ NameToAtom::iterator pos = _nameTable.find(sym);
+ if (pos == _nameTable.end())
+ return NULL;
+ return pos->second;
+}
+
+bool SymbolTable::isDefined(llvm::StringRef sym) {
+ const Atom *atom = this->findByName(sym);
+ if (atom == NULL)
+ return false;
+ if (atom->definition() == Atom::definitionUndefined)
+ return false;
+ return true;
+}
+
+const Atom *SymbolTable::replacement(const Atom *atom) {
+ AtomToAtom::iterator pos = _replacedAtoms.find(atom);
+ if (pos == _replacedAtoms.end())
+ return atom;
+ // might be chain, recurse to end
+ return this->replacement(pos->second);
+}
+
+unsigned int SymbolTable::size() {
+ return _nameTable.size();
+}
+
+void SymbolTable::undefines(std::vector<const Atom *> &undefs) {
+ for (NameToAtom::iterator it = _nameTable.begin(),
+ end = _nameTable.end(); it != end; ++it) {
+ const Atom *atom = it->second;
+ assert(atom != NULL);
+ if (atom->definition() == Atom::definitionUndefined)
+ undefs.push_back(atom);
+ }
+}
+
+} // namespace lld
OpenPOWER on IntegriCloud