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);