Refactor and comment Atom attributes.  Replace combine() with internalName() and mergeDuplicates()

llvm-svn: 146958
diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h
index b8008e4..50f39ec 100644
--- a/lld/include/lld/Core/Atom.h
+++ b/lld/include/lld/Core/Atom.h
@@ -37,19 +37,13 @@
 
   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
   };
 
-  enum Combine {
-    combineNever,            // most symbols
-    combineByName,           // weak-definition symbol
-    combineByTypeContent,    // simple constant that can be coalesced
-    combineByTypeContentDeep // complex coalescable constants
-  };
-
   enum ContentType {
     typeUnknown,            // for use with definitionUndefined
     typeCode,               // executable code
@@ -104,6 +98,12 @@
     sectionCustomRequired   // linker must place in specific section
   };
 
+  enum DeadStripKind {
+    deadStripNormal,        // linker may dead strip this atom
+    deadStripNever,         // linker must never dead strip this atom
+    deadStripAlways         // linker must remove this atom if unused
+  };
+
   struct Alignment {
     Alignment(int p2, int m = 0)
       : powerOf2(p2)
@@ -121,54 +121,114 @@
     typedef UnwindInfo *iterator;
   };
 
-  // link-once (throw away if not used)??
-  // dll import/export
+  /// name - The name of the atom. For a function atom, it is the (mangled)
+  /// name of the function. 
+  virtual llvm::StringRef name() const = 0;
+  
+  /// internalName - If the name is just a temporary label that should
+  /// not show up in the final linked image.
+  bool internalName() const { 
+    return _internalName; 
+  }
 
-  Scope scope() const { return _scope; }
-  Definition definition() const { return _definition; }
-  Combine combine() const { return _combine; }
-  ContentType contentType() const { return _contentType; }
-  Alignment alignment() const;
-  SectionChoice sectionChoice() const { return _sectionChoice; }
-  bool deadStrip() const { return _DeadStrip; }
+  /// size - the number of bytes of space this atom's content will occupy
+  /// in the final linked image.  For a function atom, it is the number
+  /// of bytes of code in the function.
+  virtual uint64_t size() const = 0;
+
+  /// scope - The visibility of this atom to other atoms.  C static functions
+  /// have scope scopeTranslationUnit.  Regular C functions have scope 
+  /// scopeGlobal.  Functions compiled with visibility=hidden have scope
+  /// scopeLinkageUnit so they can be see by other atoms being linked but not
+  /// by the OS loader.
+  Scope scope() const { 
+    return _scope; 
+  }
+  
+  /// definition - Whether this atom is a definition or represents an undefined
+  /// or tentative symbol.
+  Definition definition() const { 
+    return _definition; 
+  }
+  
+  /// mergeDuplicates - For definitionRegular atoms, this means the
+  /// atom can be silently coalesced with another atom that has the 
+  /// same name or content.
+  bool mergeDuplicates() const { 
+    return _mergeDuplicates; 
+  }
+  
+  /// contentType - The type of this atom, such as code or data.
+  ContentType contentType() const { 
+    return _contentType; 
+  }
+  
+  /// alignment - The alignment constraints on how this atom must be laid out 
+  /// in the final linked image (e.g. 16-byte aligned).
+  Alignment alignment() const {
+    return Alignment(_alignmentPowerOf2, _alignmentModulus);
+  }
+
+  /// sectionChoice - Whether this atom must be in a specially named section
+  /// in the final linked image, or if the linker can infer the section 
+  /// based on the contentType().
+  SectionChoice sectionChoice() const { 
+    return _sectionChoice; 
+  }
+  
+  /// customSectionName - If sectionChoice() != sectionBasedOnContent, then
+  /// this return the name of the section the atom should be placed into.
+  virtual llvm::StringRef customSectionName() const;
+    
+  /// deadStrip - constraints on whether the linker may dead strip away 
+  /// this atom.
+  DeadStripKind deadStrip() const { 
+    return _deadStrip; 
+  }
+  
+  /// autoHide - Whether it is ok for the linker to change the scope of this 
+  /// atom to hidden as long as all other duplicates are also autoHide.
+  bool autoHide() const {
+    return _autoHide;
+  }
+
+  /// 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_.
+  virtual ContentPermissions permissions() const;
+    
+  /// 
+  virtual void copyRawContent(uint8_t buffer[]) const = 0;
+  virtual llvm::ArrayRef<uint8_t> rawContent() const;
+
+
   bool isThumb() const { return _thumb; }
   bool isAlias() const { return _alias; }
-  bool userVisibleName() const { return _userVisibleName; }
-  bool autoHide() const;
+  
   void setLive(bool l) { _live = l; }
   bool live() const { return _live; }
-  void setOverridesDylibsWeakDef();
 
   virtual const class File *file() const = 0;
   virtual bool translationUnitSource(llvm::StringRef &path) const;
-  virtual llvm::StringRef name() const;
   virtual uint64_t objectAddress() const = 0;
-  virtual llvm::StringRef customSectionName() const;
-  virtual uint64_t size() const = 0;
-  virtual ContentPermissions permissions() const { return perm___; }
-  virtual void copyRawContent(uint8_t buffer[]) const = 0;
-  virtual llvm::ArrayRef<uint8_t> rawContent() const;
   virtual Reference::iterator referencesBegin() const;
   virtual Reference::iterator referencesEnd() const;
   virtual UnwindInfo::iterator beginUnwind() const;
   virtual UnwindInfo::iterator endUnwind() const;
 
   Atom( Definition d
-      , Combine c
       , Scope s
       , ContentType ct
       , SectionChoice sc
-      , bool UserVisibleName
-      , bool DeadStrip
+      , bool internalName
+      , DeadStripKind ds
       , bool IsThumb
       , bool IsAlias
       , Alignment a)
     : _alignmentModulus(a.modulus)
     , _alignmentPowerOf2(a.powerOf2)
     , _definition(d)
-    , _combine(c)
-    , _userVisibleName(UserVisibleName)
-    , _DeadStrip(DeadStrip)
+    , _internalName(internalName)
+    , _deadStrip(ds)
     , _thumb(IsThumb)
     , _alias(IsAlias)
     , _contentType(ct)
@@ -178,18 +238,19 @@
   virtual ~Atom();
 
 protected:
-  uint16_t _alignmentModulus;
-  uint8_t _alignmentPowerOf2;
-  Definition _definition : 3;
-  Combine _combine : 2;
-  bool _userVisibleName : 1;
-  bool _DeadStrip : 1;
-  bool _thumb : 1;
-  bool _alias : 1;
-  bool _live : 1;
-  ContentType _contentType : 8;
-  Scope _scope : 2;
+  uint16_t      _alignmentModulus;
+  uint8_t       _alignmentPowerOf2;
+  ContentType   _contentType : 8;
+  Definition    _definition : 3;
+  Scope         _scope : 2;
   SectionChoice _sectionChoice: 2;
+  bool          _internalName : 1;
+  DeadStripKind _deadStrip : 2;
+  bool          _mergeDuplicates : 1;
+  bool          _thumb : 1;
+  bool          _autoHide : 1;
+  bool          _alias : 1;
+  bool          _live : 1;
 };
 
 } // namespace lld
diff --git a/lld/include/lld/Core/UndefinedAtom.h b/lld/include/lld/Core/UndefinedAtom.h
index 815ea8d..36463ac 100644
--- a/lld/include/lld/Core/UndefinedAtom.h
+++ b/lld/include/lld/Core/UndefinedAtom.h
@@ -22,12 +22,11 @@
 public:
   UndefinedAtom(llvm::StringRef nm)
     : Atom( Atom::definitionUndefined
-          , Atom::combineNever
           , Atom::scopeLinkageUnit
           , Atom::typeUnknown
           , Atom::sectionBasedOnContent
-          , true
           , false
+          , deadStripNormal
           , false
           , false
           , Atom::Alignment(0))
diff --git a/lld/lib/Core/Atom.cpp b/lld/lib/Core/Atom.cpp
index 482a21f..889ec09 100644
--- a/lld/lib/Core/Atom.cpp
+++ b/lld/lib/Core/Atom.cpp
@@ -32,6 +32,10 @@
     return llvm::ArrayRef<uint8_t>();
   }
 
+  Atom::ContentPermissions Atom::permissions() const { 
+    return perm___; 
+  }
+
   Reference::iterator Atom::referencesBegin() const {
     return 0;
   }
diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp
index 3b77062..ebd4c0b 100644
--- a/lld/lib/Core/SymbolTable.cpp
+++ b/lld/lib/Core/SymbolTable.cpp
@@ -26,15 +26,11 @@
 
 void SymbolTable::add(const Atom &atom) {
   assert(atom.scope() != Atom::scopeTranslationUnit);
-  switch (atom.combine()) {
-  case Atom::combineNever:
-  case Atom::combineByName:
+  if ( !atom.internalName() ) {
     this->addByName(atom);
-    break;
-  case Atom::combineByTypeContent:
-  case Atom::combineByTypeContentDeep:
+  }
+  else if ( atom.mergeDuplicates() ) {
     // TO DO: support constants merging
-    break;
   }
 }
 
@@ -46,27 +42,31 @@
   NCR_Error
 };
 
-static NameCollisionResolution cases[5][5] = {
-  //regular     tentative   absolute    undef      sharedLib
+static NameCollisionResolution cases[6][6] = {
+  //regular     weak         tentative   absolute    undef      sharedLib
   {
     // first is regular
-    NCR_Error,  NCR_First,  NCR_Error,  NCR_First, NCR_First
+    NCR_Error,  NCR_First,   NCR_First,  NCR_Error,  NCR_First, NCR_First
+  },
+  {
+    // first is weak
+    NCR_Second, NCR_Weak,   NCR_Larger, NCR_Error,  NCR_First, NCR_First
   },
   {
     // first is tentative
-    NCR_Second, NCR_Larger, NCR_Error,  NCR_First, NCR_First
+    NCR_Second, NCR_Second, NCR_Larger, NCR_Error,  NCR_First, NCR_First
   },
   {
     // first is absolute
-    NCR_Error,  NCR_Error,  NCR_Error,  NCR_First, NCR_First
+    NCR_Error,  NCR_Error,  NCR_Error,  NCR_Error,  NCR_First, NCR_First
   },
   {
     // first is undef
-    NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second
+    NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second
   },
   {
     // first is sharedLib
-    NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First
+    NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First
   }
 };
 
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp
index 9b093e4..c95e061 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/Core/YamlReader.cpp
@@ -239,18 +239,17 @@
 class YAMLAtom : public Atom {
 public:
   YAMLAtom( Definition d
-          , Combine c
           , Scope s
           , ContentType ct
           , SectionChoice sc
-          , bool uvn
-          , bool dds
+          , bool intn
+          , DeadStripKind dsk
           , bool tb
           , bool al
           , Alignment a
           , YAMLFile *f
           , const char *n)
-    : Atom(d, c, s, ct, sc, uvn, dds, tb, al, a)
+    : Atom(d, s, ct, sc, intn, dsk, tb, al, a)
     , _file(f)
     , _name(n)
     , _size(0)
@@ -322,13 +321,13 @@
 private:
   const char *_name;
   Atom::Alignment _align;
-  Atom::Combine _combine;
   Atom::ContentType _type;
   Atom::Scope _scope;
   Atom::Definition _def;
   Atom::SectionChoice _sectionChoice;
+  bool _internalName;
   bool _userVisibleName;
-  bool _dontDeadStrip;
+  Atom::DeadStripKind _dontDeadStrip;
   bool _thumb;
   bool _alias;
   Reference _ref;
@@ -337,11 +336,10 @@
 YAMLAtomState::YAMLAtomState()
   : _name(NULL)
   , _align(0, 0)
-  , _combine(Atom::combineNever)
   , _type(Atom::typeData)
   , _scope(Atom::scopeGlobal)
   , _userVisibleName(true)
-  , _dontDeadStrip(false)
+  , _dontDeadStrip(Atom::deadStripNormal)
   , _thumb(false)
   , _alias(false) {
   _ref.target       = NULL;
@@ -352,8 +350,8 @@
 }
 
 void YAMLAtomState::makeAtom(YAMLFile *f) {
-  Atom *a = new YAMLAtom(_def, _combine, _scope, _type, _sectionChoice,
-                         _userVisibleName, _dontDeadStrip, _thumb, _alias,
+  Atom *a = new YAMLAtom(_def, _scope, _type, _sectionChoice,
+                         _internalName, _dontDeadStrip, _thumb, _alias,
                          _align, f, _name);
 
   f->_atoms.push_back(a);
@@ -362,13 +360,12 @@
   _name             = NULL;
   _align.powerOf2   = 0;
   _align.modulus    = 0;
-  _combine          = Atom::combineNever;
   _type             = Atom::typeData;
   _scope            = Atom::scopeGlobal;
   _def              = Atom::definitionRegular;
   _sectionChoice    = Atom::sectionBasedOnContent;
-  _userVisibleName  = true;
-  _dontDeadStrip    = false;
+  _internalName     = false;
+  _dontDeadStrip    = Atom::deadStripNormal;
   _thumb            = false;
   _alias            = false;
   _ref.target       = NULL;
diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp
index ae27c7e..711fd1a 100644
--- a/lld/lib/Core/YamlWriter.cpp
+++ b/lld/lib/Core/YamlWriter.cpp
@@ -29,8 +29,8 @@
   virtual void doFile(const class File &) { }
   virtual void doAtom(const class Atom &atom) {
     _out << "    - name:        " << atom.name() << "\n";
+    _out << "      internal-name:" << atom.internalName() << "\n";
     _out << "      definition:  " << definitionString(atom.definition()) <<"\n";
-    _out << "      user-visible:" << atom.userVisibleName() << "\n";
     _out << "      scope:       " << scopeString(atom.scope()) << "\n";
     _out << "      type:        " << typeString(atom.contentType()) << "\n";
     if (atom.referencesBegin() != atom.referencesEnd()) {