Cleaned up Atom attribues some more. Added lots of doxygen comments

llvm-svn: 147105
This commit is contained in:
Nick Kledzik 2011-12-21 23:29:36 +00:00
parent 7869d8c01e
commit f46669c828
7 changed files with 203 additions and 76 deletions

View File

@ -10,6 +10,8 @@
#ifndef LLD_CORE_ATOM_H_
#define LLD_CORE_ATOM_H_
#include <assert.h>
#include "lld/Core/Reference.h"
namespace llvm {
@ -27,21 +29,85 @@ class File;
/// is an atom. An atom has content and attributes. The content of a function
/// atom is the instructions that implement the function. The content of a
/// global variable atom is its initial bytes.
///
/// Here are some example attribute sets for common atoms. If a particular
/// attribute is not listed, the default values are: definition=regular,
/// sectionChoice=basedOnContent, scope=translationUnit, mergeDups=false,
/// autoHide=false, internalName=false, deadStrip=normal
///
/// C function: void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global
///
/// C static function: staic void func() {} <br>
/// name=func, type=code, perm=r_x
///
/// C global variable: int count = 1; <br>
/// name=count, type=data, perm=rw_, scope=global
///
/// C tentative definition: int bar; <br>
/// name=bar, type=data, perm=rw_, scope=global, definition=tentative
///
/// Uninitialized C static variable: static int stuff; <br>
/// name=stuff, type=zerofill, perm=rw_
///
/// Weak C function: __attribute__((weak)) void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global, definition=weak
///
/// Hidden C function: __attribute__((visibility("hidden"))) void foo() {}<br>
/// name=foo, type=code, perm=r_x, scope=linkageUnit
///
/// No-dead-strip function: __attribute__((used)) void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global, deadStrip=never
///
/// Non-inlined C++ inline method: inline void Foo::doit() {} <br>
/// name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global,
/// mergeDups=true, autoHide=true
///
/// Non-inlined C++ inline method whose address is taken:
/// inline void Foo::doit() {} <br>
/// name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, mergeDups=true
///
/// literal c-string: "hello" <br>
/// name=L0, internalName=true, type=cstring, perm=r__,
/// scope=linkageUnit, mergeDups=true
///
/// literal double: 1.234 <br>
/// name=L0, internalName=true, type=literal8, perm=r__,
/// scope=linkageUnit, mergeDups=true
///
/// constant: { 1,2,3 } <br>
/// name=L0, internalName=true, type=constant, perm=r__,
/// scope=linkageUnit, mergeDups=true
///
/// Pointer to initializer function: <br>
/// name=_init, internalName=true, type=initializer, perm=rw_l,
/// sectionChoice=customRequired
///
/// C function place in custom section: __attribute__((section("__foo")))
/// void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global,
/// sectionChoice=customRequired, sectionName=__foo
///
class Atom {
public:
/// The scope in which this atom is acessible to other atoms.
enum Scope {
scopeTranslationUnit, // static, private to translation unit
scopeLinkageUnit, // hidden, accessible to just atoms being linked
scopeGlobal // default
scopeTranslationUnit, ///< Accessible only to atoms in the same translation
/// unit (e.g. a C static).
scopeLinkageUnit, ///< Accessible to atoms being linked but not visible
/// to runtime loader (e.g. visibility=hidden).
scopeGlobal ///< Accessible to all atoms and visible to runtime
/// loader (e.g. visibility=default) .
};
/// Whether this atom is defined or a proxy for an undefined symbol
enum Definition {
definitionRegular, // usual C/C++ function or global variable
definitionWeak, // can be silently overridden by regular definition
definitionTentative, // C-only pre-ANSI support aka common
definitionAbsolute, // asm-only (foo = 10) not tied to any content
definitionUndefined, // Only in .o files to model reference to undef
definitionSharedLibrary // Only in shared libraries to model export
definitionRegular, ///< Normal C/C++ function or global variable.
definitionWeak, ///< Can be silently overridden by definitionRegular
definitionTentative, ///< C-only pre-ANSI support aka common.
definitionAbsolute, ///< Asm-only (foo = 10). Not tied to any content.
definitionUndefined, ///< Only in .o files to model reference to undef.
definitionSharedLibrary ///< Only in shared libraries to model export.
};
enum ContentType {
@ -113,13 +179,8 @@ public:
uint16_t modulus;
};
// MacOSX specific compact unwind info
struct UnwindInfo {
uint32_t startOffset;
uint32_t unwindInfo;
typedef UnwindInfo *iterator;
};
/// file - returns the File that produced/owns this Atom
virtual const class File& file() const = 0;
/// name - The name of the atom. For a function atom, it is the (mangled)
/// name of the function.
@ -193,29 +254,84 @@ public:
}
/// permissions - Returns the OS memory protections required for this atom's
/// content at runtime. A function atom is R_X and a global variable is RW_.
/// content at runtime. A function atom is R_X, a global variable is RW_,
/// and a read-only constant is R__.
virtual ContentPermissions permissions() const;
///
virtual void copyRawContent(uint8_t buffer[]) const = 0;
/// isThumb - only applicable to ARM code. Tells the linker if the code
/// uses thumb or arm instructions. The linker needs to know this to
/// set the low bit of pointers to thumb functions.
bool isThumb() const {
return _thumb;
}
/// isAlias - means this is a zero size atom that exists to provide an
/// alternate name for another atom. Alias atoms must have a special
/// Reference to the atom they alias which the layout engine recognizes
/// and forces the alias atom to layout right before the target atom.
bool isAlias() const {
return _alias;
}
/// rawContent - returns a reference to the raw (unrelocated) bytes of
/// this Atom's content.
virtual llvm::ArrayRef<uint8_t> rawContent() const;
/// referencesBegin - used to start iterating this Atom's References
virtual Reference::iterator referencesBegin() const;
bool isThumb() const { return _thumb; }
bool isAlias() const { return _alias; }
/// referencesEnd - used to end iterating this Atom's References
virtual Reference::iterator referencesEnd() const;
/// setLive - sets or clears the liveness bit. Used by linker to do
/// dead code stripping.
void setLive(bool l) { _live = l; }
/// live - returns the liveness bit. Used by linker to do
/// dead code stripping.
bool live() const { return _live; }
virtual const class File *file() const = 0;
virtual bool translationUnitSource(llvm::StringRef &path) const;
virtual uint64_t objectAddress() const = 0;
virtual Reference::iterator referencesBegin() const;
virtual Reference::iterator referencesEnd() const;
virtual UnwindInfo::iterator beginUnwind() const;
virtual UnwindInfo::iterator endUnwind() const;
/// ordinal - returns a value for the order of this Atom within its file.
/// This is used by the linker to order the layout of Atoms so that
/// the resulting image is stable and reproducible.
uint64_t ordinal() const {
assert(_mode == modeOrdinal);
return _address;
}
/// sectionOffset - returns the section offset assigned to this Atom within
/// its final section.
uint64_t sectionOffset() const {
assert(_mode == modeSectionOffset);
return _address;
}
Atom( Definition d
/// finalAddress - returns the address assigned to Atom within the final
/// linked image.
uint64_t finalAddress() const {
assert(_mode == modeFinalAddress);
return _address;
}
/// setSectionOffset - assigns an offset within a section in the final
/// linked image.
void setSectionOffset(uint64_t off) {
assert(_mode != modeFinalAddress);
_address = off;
_mode = modeSectionOffset;
}
/// setSectionOffset - assigns an offset within a section in the final
/// linked image.
void setFinalAddress(uint64_t addr) {
assert(_mode == modeSectionOffset);
_address = addr;
_mode = modeFinalAddress;
}
/// constructor
Atom( uint64_t ord
, Definition d
, Scope s
, ContentType ct
, SectionChoice sc
@ -224,20 +340,31 @@ public:
, bool IsThumb
, bool IsAlias
, Alignment a)
: _alignmentModulus(a.modulus)
: _address(ord)
, _alignmentModulus(a.modulus)
, _alignmentPowerOf2(a.powerOf2)
, _definition(d)
, _internalName(internalName)
, _deadStrip(ds)
, _mode(modeOrdinal)
, _thumb(IsThumb)
, _alias(IsAlias)
, _contentType(ct)
, _scope(s)
, _sectionChoice(sc) {}
virtual ~Atom();
protected:
/// The memory for Atom objects is always managed by the owning File
/// object. Therefore, no one but the owning File object should call
/// delete on an Atom. In fact, some File objects may bulk allocate
/// an array of Atoms, so they cannot be individually deleted by anyone.
virtual ~Atom();
/// The __address field has different meanings throughout the life of an Atom.
enum AddressMode { modeOrdinal, modeSectionOffset, modeFinalAddress };
uint64_t _address;
uint16_t _alignmentModulus;
uint8_t _alignmentPowerOf2;
ContentType _contentType : 8;
@ -246,6 +373,7 @@ protected:
SectionChoice _sectionChoice: 2;
bool _internalName : 1;
DeadStripKind _deadStrip : 2;
AddressMode _mode : 2;
bool _mergeDuplicates : 1;
bool _thumb : 1;
bool _autoHide : 1;

View File

@ -34,6 +34,9 @@ public:
virtual bool justInTimeforEachAtom( llvm::StringRef name
, AtomHandler &) const = 0;
virtual bool translationUnitSource(llvm::StringRef &path) const;
private:
llvm::StringRef _path;
};

View File

@ -20,8 +20,9 @@ namespace lld {
/// It exists as a place holder for a future atom.
class UndefinedAtom : public Atom {
public:
UndefinedAtom(llvm::StringRef nm)
: Atom( Atom::definitionUndefined
UndefinedAtom(llvm::StringRef nm, const File& f)
: Atom( 0,
Atom::definitionUndefined
, Atom::scopeLinkageUnit
, Atom::typeUnknown
, Atom::sectionBasedOnContent
@ -30,15 +31,11 @@ public:
, false
, false
, Atom::Alignment(0))
, _name(nm) {}
, _name(nm), _file(f) {}
// overrides of Atom
virtual const File *file() const {
return 0;
}
virtual bool translationUnitSource(llvm::StringRef path) const {
return false;
virtual const File& file() const {
return _file;
}
virtual llvm::StringRef name() const {
@ -58,6 +55,7 @@ protected:
virtual ~UndefinedAtom() {}
llvm::StringRef _name;
const File& _file;
};
} // namespace lld

View File

@ -16,10 +16,6 @@ namespace lld {
Atom::~Atom() {}
bool Atom::translationUnitSource(llvm::StringRef &path) const {
return false;
}
llvm::StringRef Atom::name() const {
return llvm::StringRef();
}
@ -44,12 +40,5 @@ namespace lld {
return 0;
}
Atom::UnwindInfo::iterator Atom::beginUnwind() const{
return 0;
}
Atom::UnwindInfo::iterator Atom::endUnwind() const{
return 0;
}
} // namespace lld

View File

@ -13,4 +13,9 @@ namespace lld {
File::~File() {}
bool File::translationUnitSource(llvm::StringRef &path) const {
return false;
}
}

View File

@ -183,14 +183,14 @@ void Resolver::updateReferences() {
void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
// if -why_live cares about this symbol, then dump chain
if ((previous->referer != NULL) && _platform.printWhyLive(atom.name())) {
llvm::errs() << atom.name() << " from " << atom.file()->path() << "\n";
llvm::errs() << atom.name() << " from " << atom.file().path() << "\n";
int depth = 1;
for (WhyLiveBackChain *p = previous; p != NULL;
p = p->previous, ++depth) {
for (int i = depth; i > 0; --i)
llvm::errs() << " ";
llvm::errs() << p->referer->name() << " from "
<< p->referer->file()->path() << "\n";
<< p->referer->file().path() << "\n";
}
}

View File

@ -238,7 +238,8 @@ bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
class YAMLAtom : public Atom {
public:
YAMLAtom( Definition d
YAMLAtom( uint64_t ord
, Definition d
, Scope s
, ContentType ct
, SectionChoice sc
@ -247,18 +248,18 @@ public:
, bool tb
, bool al
, Alignment a
, YAMLFile *f
, YAMLFile& f
, const char *n)
: Atom(d, s, ct, sc, intn, dsk, tb, al, a)
: Atom(ord, d, s, ct, sc, intn, dsk, tb, al, a)
, _file(f)
, _name(n)
, _size(0)
, _refStartIndex(f->_lastRefIndex)
, _refEndIndex(f->_references.size()) {
f->_lastRefIndex = _refEndIndex;
, _refStartIndex(f._lastRefIndex)
, _refEndIndex(f._references.size()) {
f._lastRefIndex = _refEndIndex;
}
virtual const class File *file() const {
virtual const class File& file() const {
return _file;
}
@ -282,7 +283,7 @@ public:
virtual Reference::iterator referencesBegin() const;
virtual Reference::iterator referencesEnd() const;
private:
YAMLFile *_file;
YAMLFile& _file;
const char *_name;
unsigned long _size;
unsigned int _refStartIndex;
@ -290,14 +291,14 @@ private:
};
Reference::iterator YAMLAtom::referencesBegin() const {
if (_file->_references.size() < _refStartIndex)
return (Reference::iterator)&_file->_references[_refStartIndex];
if (_file._references.size() < _refStartIndex)
return (Reference::iterator)&_file._references[_refStartIndex];
return 0;
}
Reference::iterator YAMLAtom::referencesEnd() const {
if (_file->_references.size() < _refEndIndex)
return (Reference::iterator)&_file->_references[_refEndIndex];
if (_file._references.size() < _refEndIndex)
return (Reference::iterator)&_file._references[_refEndIndex];
return 0;
}
@ -316,9 +317,10 @@ public:
void setFixupTarget(const char *n);
void addFixup(YAMLFile *f);
void makeAtom(YAMLFile *);
void makeAtom(YAMLFile&);
private:
uint64_t _ordinal;
const char *_name;
Atom::Alignment _align;
Atom::ContentType _type;
@ -334,7 +336,8 @@ private:
};
YAMLAtomState::YAMLAtomState()
: _name(NULL)
: _ordinal(0)
, _name(NULL)
, _align(0, 0)
, _type(Atom::typeData)
, _scope(Atom::scopeGlobal)
@ -349,13 +352,14 @@ YAMLAtomState::YAMLAtomState()
_ref.flags = 0;
}
void YAMLAtomState::makeAtom(YAMLFile *f) {
Atom *a = new YAMLAtom(_def, _scope, _type, _sectionChoice,
void YAMLAtomState::makeAtom(YAMLFile& f) {
Atom *a = new YAMLAtom(_ordinal, _def, _scope, _type, _sectionChoice,
_internalName, _dontDeadStrip, _thumb, _alias,
_align, f, _name);
f->_atoms.push_back(a);
f._atoms.push_back(a);
++_ordinal;
// reset state for next atom
_name = NULL;
_align.powerOf2 = 0;
@ -472,7 +476,7 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
if (entry->beginDocument) {
if (file != NULL) {
if (haveAtom) {
atomState.makeAtom(file);
atomState.makeAtom(*file);
haveAtom = false;
}
result.push_back(file);
@ -502,7 +506,7 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
if (depthForAtoms == entry->depth) {
if (entry->beginSequence) {
if (haveAtom) {
atomState.makeAtom(file);
atomState.makeAtom(*file);
haveAtom = false;
}
}
@ -546,7 +550,7 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
lastDepth = entry->depth;
}
if (haveAtom) {
atomState.makeAtom(file);
atomState.makeAtom(*file);
}
result.push_back(file);