Cleaned up Atom attribues some more. Added lots of doxygen comments
llvm-svn: 147105
diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h
index 50f39ec..a3fb321 100644
--- a/lld/include/lld/Core/Atom.h
+++ b/lld/include/lld/Core/Atom.h
@@ -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 @@
/// 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 @@
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 @@
}
/// 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 @@
, 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 @@
SectionChoice _sectionChoice: 2;
bool _internalName : 1;
DeadStripKind _deadStrip : 2;
+ AddressMode _mode : 2;
bool _mergeDuplicates : 1;
bool _thumb : 1;
bool _autoHide : 1;
diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h
index 03d7887..0eaa34c 100644
--- a/lld/include/lld/Core/File.h
+++ b/lld/include/lld/Core/File.h
@@ -34,6 +34,9 @@
virtual bool justInTimeforEachAtom( llvm::StringRef name
, AtomHandler &) const = 0;
+ virtual bool translationUnitSource(llvm::StringRef &path) const;
+
+
private:
llvm::StringRef _path;
};
diff --git a/lld/include/lld/Core/UndefinedAtom.h b/lld/include/lld/Core/UndefinedAtom.h
index 36463ac..72a3edc 100644
--- a/lld/include/lld/Core/UndefinedAtom.h
+++ b/lld/include/lld/Core/UndefinedAtom.h
@@ -20,8 +20,9 @@
/// 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 @@
, 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 @@
virtual ~UndefinedAtom() {}
llvm::StringRef _name;
+ const File& _file;
};
} // namespace lld
diff --git a/lld/lib/Core/Atom.cpp b/lld/lib/Core/Atom.cpp
index 889ec09..29aa1c8 100644
--- a/lld/lib/Core/Atom.cpp
+++ b/lld/lib/Core/Atom.cpp
@@ -16,10 +16,6 @@
Atom::~Atom() {}
- bool Atom::translationUnitSource(llvm::StringRef &path) const {
- return false;
- }
-
llvm::StringRef Atom::name() const {
return llvm::StringRef();
}
@@ -44,12 +40,5 @@
return 0;
}
- Atom::UnwindInfo::iterator Atom::beginUnwind() const{
- return 0;
- }
-
- Atom::UnwindInfo::iterator Atom::endUnwind() const{
- return 0;
- }
} // namespace lld
diff --git a/lld/lib/Core/File.cpp b/lld/lib/Core/File.cpp
index e123d5e..09c3f8a 100644
--- a/lld/lib/Core/File.cpp
+++ b/lld/lib/Core/File.cpp
@@ -13,4 +13,9 @@
File::~File() {}
+bool File::translationUnitSource(llvm::StringRef &path) const {
+ return false;
+}
+
+
}
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index b3be26b..c3b8375 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -183,14 +183,14 @@
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";
}
}
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp
index c95e061..6250939 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/Core/YamlReader.cpp
@@ -238,7 +238,8 @@
class YAMLAtom : public Atom {
public:
- YAMLAtom( Definition d
+ YAMLAtom( uint64_t ord
+ , Definition d
, Scope s
, ContentType ct
, SectionChoice sc
@@ -247,18 +248,18 @@
, 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 @@
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 @@
};
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 @@
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 @@
};
YAMLAtomState::YAMLAtomState()
- : _name(NULL)
+ : _ordinal(0)
+ , _name(NULL)
, _align(0, 0)
, _type(Atom::typeData)
, _scope(Atom::scopeGlobal)
@@ -349,13 +352,14 @@
_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 @@
if (entry->beginDocument) {
if (file != NULL) {
if (haveAtom) {
- atomState.makeAtom(file);
+ atomState.makeAtom(*file);
haveAtom = false;
}
result.push_back(file);
@@ -502,7 +506,7 @@
if (depthForAtoms == entry->depth) {
if (entry->beginSequence) {
if (haveAtom) {
- atomState.makeAtom(file);
+ atomState.makeAtom(*file);
haveAtom = false;
}
}
@@ -546,7 +550,7 @@
lastDepth = entry->depth;
}
if (haveAtom) {
- atomState.makeAtom(file);
+ atomState.makeAtom(*file);
}
result.push_back(file);