Use the LLVM RTTI library.

llvm-svn: 153912
This commit is contained in:
Michael J. Spencer 2012-04-02 23:56:36 +00:00
parent 51e318737a
commit b495562b5d
9 changed files with 58 additions and 88 deletions

View File

@ -18,21 +18,15 @@ namespace lld {
/// It exists to represent content at fixed addresses in memory. /// It exists to represent content at fixed addresses in memory.
class AbsoluteAtom : public Atom { class AbsoluteAtom : public Atom {
public: public:
virtual Definition definition() const {
return Atom::definitionAbsolute;
}
/// like dynamic_cast, if atom is definitionAbsolute
/// returns atom cast to AbsoluteAtom*, else returns nullptr
virtual const AbsoluteAtom* absoluteAtom() const {
return this;
}
virtual uint64_t value() const = 0; virtual uint64_t value() const = 0;
static inline bool classof(const Atom *a) {
return a->definition() == definitionAbsolute;
}
static inline bool classof(const AbsoluteAtom *) { return true; }
protected: protected:
AbsoluteAtom() {} AbsoluteAtom() : Atom(definitionAbsolute) {}
virtual ~AbsoluteAtom() {} virtual ~AbsoluteAtom() {}
}; };

View File

@ -21,10 +21,6 @@ namespace llvm {
namespace lld { namespace lld {
class File; class File;
class DefinedAtom;
class UndefinedAtom;
class SharedLibraryAtom;
class AbsoluteAtom;
/// ///
/// The linker has a Graph Theory model of linking. An object file is seen /// The linker has a Graph Theory model of linking. An object file is seen
@ -52,33 +48,22 @@ public:
/// definition - Whether this atom is a definition or represents an undefined /// definition - Whether this atom is a definition or represents an undefined
/// symbol. /// symbol.
virtual Definition definition() const = 0; Definition definition() const { return _definition; };
/// definedAtom - like dynamic_cast, if atom is definitionRegular
/// returns atom cast to DefinedAtom*, else returns nullptr;
virtual const DefinedAtom* definedAtom() const { return nullptr; }
/// undefinedAtom - like dynamic_cast, if atom is definitionUndefined static inline bool classof(const Atom *a) { return true; }
/// returns atom cast to UndefinedAtom*, else returns nullptr;
virtual const UndefinedAtom* undefinedAtom() const { return nullptr; }
/// sharedLibraryAtom - like dynamic_cast, if atom is definitionSharedLibrary
/// returns atom cast to SharedLibraryAtom*, else returns nullptr;
virtual const SharedLibraryAtom* sharedLibraryAtom() const { return nullptr; }
/// absoluteAtom - like dynamic_cast, if atom is definitionAbsolute
/// returns atom cast to AbsoluteAtom*, else returns nullptr;
virtual const AbsoluteAtom* absoluteAtom() const { return nullptr; }
protected: protected:
/// Atom is an abstract base class. Only subclasses can access constructor. /// Atom is an abstract base class. Only subclasses can access constructor.
Atom() {} Atom(Definition def) : _definition(def) {}
/// The memory for Atom objects is always managed by the owning File /// The memory for Atom objects is always managed by the owning File
/// object. Therefore, no one but the owning File object should call /// object. Therefore, no one but the owning File object should call
/// delete on an Atom. In fact, some File objects may bulk allocate /// delete on an Atom. In fact, some File objects may bulk allocate
/// an array of Atoms, so they cannot be individually deleted by anyone. /// an array of Atoms, so they cannot be individually deleted by anyone.
virtual ~Atom() {} virtual ~Atom() {}
private:
Definition _definition;
}; };
} // namespace lld } // namespace lld

View File

@ -88,15 +88,6 @@ class File;
/// ///
class DefinedAtom : public Atom { class DefinedAtom : public Atom {
public: public:
/// Whether this atom is defined or a proxy for an undefined symbol
virtual Definition definition() const {
return Atom::definitionRegular;
}
virtual const DefinedAtom* definedAtom() const {
return this;
}
/// The scope in which this atom is acessible to other atoms. /// The scope in which this atom is acessible to other atoms.
enum Scope { enum Scope {
scopeTranslationUnit, ///< Accessible only to atoms in the same translation scopeTranslationUnit, ///< Accessible only to atoms in the same translation
@ -293,11 +284,15 @@ public:
/// Returns an iterator to the end of this Atom's References /// Returns an iterator to the end of this Atom's References
virtual reference_iterator referencesEnd() const = 0; virtual reference_iterator referencesEnd() const = 0;
static inline bool classof(const Atom *a) {
return a->definition() == definitionRegular;
}
static inline bool classof(const DefinedAtom *) { return true; }
protected: protected:
/// DefinedAtom is an abstract base class. /// DefinedAtom is an abstract base class.
/// Only subclasses can access constructor. /// Only subclasses can access constructor.
DefinedAtom() { } DefinedAtom() : Atom(definitionRegular) { }
/// The memory for DefinedAtom objects is always managed by the owning File /// The memory for DefinedAtom objects is always managed by the owning File
/// object. Therefore, no one but the owning File object should call /// object. Therefore, no one but the owning File object should call

View File

@ -22,16 +22,6 @@ namespace lld {
/// It exists to represent a symbol which will be bound at runtime. /// It exists to represent a symbol which will be bound at runtime.
class SharedLibraryAtom : public Atom { class SharedLibraryAtom : public Atom {
public: public:
virtual Definition definition() const {
return Atom::definitionSharedLibrary;
}
/// like dynamic_cast, if atom is definitionSharedLibrary
/// returns atom cast to SharedLibraryAtom*, else returns nullptr
virtual const SharedLibraryAtom* sharedLibraryAtom() const {
return this;
}
/// Returns shared library name used to load it at runtime. /// Returns shared library name used to load it at runtime.
/// On linux that is the DT_NEEDED name. /// On linux that is the DT_NEEDED name.
/// On Darwin it is the LC_DYLIB_LOAD dylib name. /// On Darwin it is the LC_DYLIB_LOAD dylib name.
@ -40,9 +30,14 @@ public:
/// Returns if shared library symbol can be missing at runtime and if /// Returns if shared library symbol can be missing at runtime and if
/// so the loader should silently resolve address of symbol to be nullptr. /// so the loader should silently resolve address of symbol to be nullptr.
virtual bool canBeNullAtRuntime() const = 0; virtual bool canBeNullAtRuntime() const = 0;
static inline bool classof(const Atom *a) {
return a->definition() == definitionSharedLibrary;
}
static inline bool classof(const SharedLibraryAtom *) { return true; }
protected: protected:
SharedLibraryAtom() {} SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
virtual ~SharedLibraryAtom() {} virtual ~SharedLibraryAtom() {}
}; };

View File

@ -18,16 +18,6 @@ namespace lld {
/// It exists as a place holder for a future atom. /// It exists as a place holder for a future atom.
class UndefinedAtom : public Atom { class UndefinedAtom : public Atom {
public: public:
virtual Definition definition() const {
return Atom::definitionUndefined;
}
/// like dynamic_cast, if atom is definitionUndefined
/// returns atom cast to UndefinedAtom*, else returns nullptr
virtual const UndefinedAtom* undefinedAtom() const {
return this;
}
/// Whether this undefined symbol needs to be resolved, /// Whether this undefined symbol needs to be resolved,
/// or whether it can just evaluate to nullptr. /// or whether it can just evaluate to nullptr.
/// This concept is often called "weak", but that term /// This concept is often called "weak", but that term
@ -61,9 +51,13 @@ public:
virtual CanBeNull canBeNull() const = 0; virtual CanBeNull canBeNull() const = 0;
static inline bool classof(const Atom *a) {
return a->definition() == definitionUndefined;
}
static inline bool classof(const UndefinedAtom *) { return true; }
protected: protected:
UndefinedAtom() {} UndefinedAtom() : Atom(definitionUndefined) {}
virtual ~UndefinedAtom() {} virtual ~UndefinedAtom() {}
}; };

View File

@ -15,6 +15,7 @@
#include "lld/Core/SymbolTable.h" #include "lld/Core/SymbolTable.h"
#include "lld/Core/UndefinedAtom.h" #include "lld/Core/UndefinedAtom.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <algorithm> #include <algorithm>
@ -33,7 +34,7 @@ public:
if ( _liveAtoms.count(atom) ) if ( _liveAtoms.count(atom) )
return false; return false;
// don't remove if marked never-dead-strip // don't remove if marked never-dead-strip
if ( const DefinedAtom* defAtom = atom->definedAtom() ) { if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(atom)) {
if ( defAtom->deadStrip() == DefinedAtom::deadStripNever ) if ( defAtom->deadStrip() == DefinedAtom::deadStripNever )
return false; return false;
} }
@ -194,7 +195,7 @@ void Resolver::resolveUndefines() {
std::vector<const Atom *> tents; std::vector<const Atom *> tents;
for (std::vector<const Atom *>::iterator ait = _atoms.begin(); for (std::vector<const Atom *>::iterator ait = _atoms.begin();
ait != _atoms.end(); ++ait) { ait != _atoms.end(); ++ait) {
if ( const DefinedAtom* defAtom = (*ait)->definedAtom() ) { if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(*ait)) {
if ( defAtom->merge() == DefinedAtom::mergeAsTentative ) if ( defAtom->merge() == DefinedAtom::mergeAsTentative )
tents.push_back(defAtom); tents.push_back(defAtom);
} }
@ -206,7 +207,8 @@ void Resolver::resolveUndefines() {
llvm::StringRef tentName = (*dit)->name(); llvm::StringRef tentName = (*dit)->name();
const Atom *curAtom = _symbolTable.findByName(tentName); const Atom *curAtom = _symbolTable.findByName(tentName);
assert(curAtom != nullptr); assert(curAtom != nullptr);
if ( const DefinedAtom* curDefAtom = curAtom->definedAtom() ) { if (const DefinedAtom* curDefAtom =
llvm::dyn_cast<DefinedAtom>(curAtom)) {
if (curDefAtom->merge() == DefinedAtom::mergeAsTentative ) if (curDefAtom->merge() == DefinedAtom::mergeAsTentative )
_inputFiles.searchLibraries(tentName, searchDylibs, _inputFiles.searchLibraries(tentName, searchDylibs,
true, true, *this); true, true, *this);
@ -221,7 +223,7 @@ void Resolver::resolveUndefines() {
// to the new defined atom // to the new defined atom
void Resolver::updateReferences() { void Resolver::updateReferences() {
for (auto ait = _atoms.begin(); ait != _atoms.end(); ++ait) { for (auto ait = _atoms.begin(); ait != _atoms.end(); ++ait) {
if ( const DefinedAtom* defAtom = (*ait)->definedAtom() ) { if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(*ait)) {
for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd(); for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
rit != end; ++rit) { rit != end; ++rit) {
const Reference* ref = *rit; const Reference* ref = *rit;
@ -259,7 +261,7 @@ void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
WhyLiveBackChain thisChain; WhyLiveBackChain thisChain;
thisChain.previous = previous; thisChain.previous = previous;
thisChain.referer = &atom; thisChain.referer = &atom;
if ( const DefinedAtom* defAtom = atom.definedAtom() ) { if ( const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(&atom)) {
for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd(); for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
rit != end; ++rit) { rit != end; ++rit) {
const Reference* ref = *rit; const Reference* ref = *rit;
@ -342,7 +344,7 @@ void Resolver::removeCoalescedAwayAtoms() {
void Resolver::checkDylibSymbolCollisions() { void Resolver::checkDylibSymbolCollisions() {
for (std::vector<const Atom *>::const_iterator it = _atoms.begin(); for (std::vector<const Atom *>::const_iterator it = _atoms.begin();
it != _atoms.end(); ++it) { it != _atoms.end(); ++it) {
const DefinedAtom* defAtom = (*it)->definedAtom(); const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(*it);
if (defAtom == nullptr) if (defAtom == nullptr)
continue; continue;
if ( defAtom->merge() != DefinedAtom::mergeAsTentative ) if ( defAtom->merge() != DefinedAtom::mergeAsTentative )
@ -389,25 +391,23 @@ void Resolver::resolve() {
} }
void Resolver::MergedFile::addAtom(const Atom& atom) { void Resolver::MergedFile::addAtom(const Atom& atom) {
if ( const DefinedAtom* defAtom = atom.definedAtom() ) { if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(&atom)) {
_definedAtoms._atoms.push_back(defAtom); _definedAtoms._atoms.push_back(defAtom);
} } else if (const UndefinedAtom* undefAtom =
else if ( const UndefinedAtom* undefAtom = atom.undefinedAtom() ) { llvm::dyn_cast<UndefinedAtom>(&atom)) {
_undefinedAtoms._atoms.push_back(undefAtom); _undefinedAtoms._atoms.push_back(undefAtom);
} } else if (const SharedLibraryAtom* slAtom =
else if ( const SharedLibraryAtom* slAtom = atom.sharedLibraryAtom() ) { llvm::dyn_cast<SharedLibraryAtom>(&atom)) {
_sharedLibraryAtoms._atoms.push_back(slAtom); _sharedLibraryAtoms._atoms.push_back(slAtom);
} } else if (const AbsoluteAtom* abAtom = llvm::dyn_cast<AbsoluteAtom>(&atom)) {
else if ( const AbsoluteAtom* abAtom = atom.absoluteAtom() ) {
_absoluteAtoms._atoms.push_back(abAtom); _absoluteAtoms._atoms.push_back(abAtom);
} } else {
else {
assert(0 && "atom has unknown definition kind"); assert(0 && "atom has unknown definition kind");
} }
} }
void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) { void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
for(std::vector<const Atom*>::iterator it=all.begin(); it != all.end(); ++it) { for(std::vector<const Atom*>::iterator it=all.begin(); it != all.end(); ++it){
this->addAtom(**it); this->addAtom(**it);
} }
} }

View File

@ -20,6 +20,7 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include <algorithm> #include <algorithm>
@ -160,8 +161,10 @@ void SymbolTable::addByName(const Atom & newAtom) {
} }
break; break;
case NCR_DupUndef: { case NCR_DupUndef: {
const UndefinedAtom* existingUndef = existing->undefinedAtom(); const UndefinedAtom* existingUndef =
const UndefinedAtom* newUndef = newAtom.undefinedAtom(); llvm::dyn_cast<UndefinedAtom>(existing);
const UndefinedAtom* newUndef =
llvm::dyn_cast<UndefinedAtom>(&newAtom);
assert(existingUndef != nullptr); assert(existingUndef != nullptr);
assert(newUndef != nullptr); assert(newUndef != nullptr);
if ( existingUndef->canBeNull() == newUndef->canBeNull() ) { if ( existingUndef->canBeNull() == newUndef->canBeNull() ) {
@ -176,8 +179,10 @@ void SymbolTable::addByName(const Atom & newAtom) {
} }
break; break;
case NCR_DupShLib: { case NCR_DupShLib: {
const SharedLibraryAtom* existingShLib = existing->sharedLibraryAtom(); const SharedLibraryAtom* existingShLib =
const SharedLibraryAtom* newShLib = newAtom.sharedLibraryAtom(); llvm::dyn_cast<SharedLibraryAtom>(existing);
const SharedLibraryAtom* newShLib =
llvm::dyn_cast<SharedLibraryAtom>(&newAtom);
assert(existingShLib != nullptr); assert(existingShLib != nullptr);
assert(newShLib != nullptr); assert(newShLib != nullptr);
if ( (existingShLib->canBeNullAtRuntime() if ( (existingShLib->canBeNullAtRuntime()

View File

@ -38,6 +38,7 @@
#include "lld/Core/Reference.h" #include "lld/Core/Reference.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Casting.h"
namespace lld { namespace lld {
@ -57,7 +58,7 @@ void GOTPass::perform() {
if ( _platform.isGOTAccess(ref->kind(), canBypassGOT) ) { if ( _platform.isGOTAccess(ref->kind(), canBypassGOT) ) {
const Atom* target = ref->target(); const Atom* target = ref->target();
assert(target != nullptr); assert(target != nullptr);
const DefinedAtom* defTarget = target->definedAtom(); const DefinedAtom* defTarget = llvm::dyn_cast<DefinedAtom>(target);
bool replaceTargetWithGOTAtom = false; bool replaceTargetWithGOTAtom = false;
if ( target->definition() == Atom::definitionSharedLibrary ) { if ( target->definition() == Atom::definitionSharedLibrary ) {
// Accesses to shared library symbols must go through GOT. // Accesses to shared library symbols must go through GOT.

View File

@ -21,6 +21,7 @@
#include "lld/Core/Reference.h" #include "lld/Core/Reference.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Casting.h"
namespace lld { namespace lld {
@ -47,8 +48,8 @@ void StubsPass::perform() {
if ( target->definition() == Atom::definitionSharedLibrary ) { if ( target->definition() == Atom::definitionSharedLibrary ) {
// Calls to shared libraries go through stubs. // Calls to shared libraries go through stubs.
replaceCalleeWithStub = true; replaceCalleeWithStub = true;
} } else if (const DefinedAtom* defTarget =
else if ( const DefinedAtom* defTarget = target->definedAtom() ) { llvm::dyn_cast<DefinedAtom>(target)) {
if ( defTarget->interposable() != DefinedAtom::interposeNo ) { if ( defTarget->interposable() != DefinedAtom::interposeNo ) {
// Calls to interposable functions in same linkage unit // Calls to interposable functions in same linkage unit
// must also go through a stub. // must also go through a stub.